1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| 三角形三元组
记T(n)为第n个三角形数,因此T(n) = n(n+1)/2。
记dT(n)为T(n)的约数数目。 例如:T(7) = 28,因此dT(7) = 6。
记Tr(n)为满足1 ≤ i < j < k ≤ n和dT(i) > dT(j) > dT(k)的三元组(i, j, k)的数目。 已知Tr(20) = 14,Tr(100) = 5772以及Tr(1000) = 11174776。
求Tr(60 000 000)。 给出其最后18位数字作为你的答案。
我的思路:最后18位数字就是取模1e18. 观察到T是什么不重要,但是dT是什么很重要.
首先对n*(n+1)质因数分解,然后根据约数数目是积性函数的性质,用质因数算出来dT,得到一个序列. 然后用树状数组维护偏序关系,设dp[i][l]是以i结尾长度l+1的数组的个数是多少.
给你一个参考欧拉筛实现,可以用vis最小质因数在log时间内分解n和(n+1). int vis[1000010];//存最小质因数,负的表示质数表中的位置(负的) int p[100010],ptop=0;//存质数 short mu[1000010];//莫比乌斯函数 int musu[1000010];//梅滕斯函数,莫比乌斯前缀和 int phi[1000010];//欧拉函数 long long phisu[1000010];//欧拉函数前缀和 int d[1000010];//存每个数的约数个数 int mnnum[1000010];//最小质因子出现次数 void sieve(int n){//[1,n] phi[1]=1;phisu[1]=1;mu[1]=1;musu[1]=1;d[1]=1; int tmp; for(int i=2;i<=n;++i){ if(!vis[i]){ vis[i]=-(++ptop); p[ptop]=i; mu[i]=-1;// phi[i]=i-1;// d[i]=2;// mnnum[i]=1;// } for(int j=1;j<=ptop&&i*p[j]<=n;++j){ vis[i*p[j]]=p[j]; if(i%p[j]==0){ phi[i*p[j]]=phi[i]*p[j];// mnnum[i*p[j]]=mnnum[i]+1;// d[i*p[j]]=d[i]/mnnum[i*p[j]]*(mnnum[i*p[j]]+1);// break; }else{ mu[i*p[j]]=-mu[i];// phi[i*p[j]]=phi[i]*(p[j]-1);// mnnum[i*p[j]]=1;// d[i*p[j]]=d[i]*2;// } } musu[i]=musu[i-1]+mu[i];// phisu[i]=phisu[i-1]+phi[i];// } } 请给我完整c++代码实现,特别注意取模.
|