[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
",ans);
37     }
38     return 0;
39 }
原文地址:https://www.cnblogs.com/skylee03/p/7735229.html