[HAOI2012]外星人
题目大意:
告诉你一个数n,求满足φ^x(n)=1的x。
思路:
首先我们可以发现满足φ(n)=1的数只有2,也就是说你得到最终的结果,最后一步肯定是φ(2)。
同时,可以发现φ(φ(2^k))=φ(2^(k-1)),因为1~2^k中间有且仅有奇数与2^k互质,个数是2^(k-1)个。
φ是个积性函数,也就是说φ(n)=φ(p1^q1)*φ(p2^q2)*...*φ(pm^qm)。
对于只有一种质因数的n, φ(n)=φ(p^q)=p^q*(1-1/p)=(p-1)*(p^q-1)。
因此我们可以发现,每次φ下去的时候都会往里面加若干个质因数2,而对于偶数,每次会消掉一个质因数2。
由于我们最后得到答案都要经过φ(2),原问题转化为可以消掉多少个2,也就是总共会产生多少个2。
预处理出每个质因数最后能分解出多少个2,累加起来就是总共要消灭的2的个数。
预处理的时候可以用类似于线性筛的方法做。
注意如果一开始就没有质因数2,那就要多花一步来得到一个2。
1 #include<cstdio> 2 #include<cctype> 3 typedef long long int64; 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 const int P=100001,N=9592; 12 int f[P],prime[N],cnt; 13 inline void pret() { 14 f[1]=1; 15 for(register int i=2;i<P;i++) { 16 if(!f[i]) { 17 prime[cnt++]=i; 18 f[i]=f[i-1]; 19 } 20 for(register int j=0;j<cnt;j++) { 21 if(i*prime[j]>=P) break; 22 f[i*prime[j]]=f[i]+f[prime[j]]; 23 if(!(i%prime[j])) break; 24 } 25 } 26 } 27 int main() { 28 pret(); 29 for(register int T=getint();T;T--) { 30 int64 ans=1; 31 for(register int m=getint();m;m--) { 32 const int p=getint(),q=getint(); 33 ans+=(int64)f[p]*q; 34 if(p==2) ans--; 35 } 36 printf("%lld\n",ans); 37 } 38 return 0; 39 }