[COCI 2013/2014 ROUND 4] guma
分析:
可以用欧拉函数来解决。对于要将一个小矩形等分成n份,那么需要在1/n,2/n,3/n...(n-1)/n处各切一刀,将这n-1个分数化成最简分数后,分母的集合即时n的所有因数(不包括1),且分母与分子互质,那么对于某个分母b来说,一共会有φ(b)个,则等分成n份要切
∑φ(ai) (ai为n的因数,不包括1但包括n)
对于一个分母b如果之前被切过那么只需延长它即可,不用再切,这样我们就可以得到一个算法:
对于每个数找到它的所有因数,如果出现过就不管,没有出现过就把答案加上这个因数的欧拉函数值并把这个数标记为出现过,最后就能得到答案。
下面就是代码
1 #include<cstdio> 2 #include<cmath> 3 #define maxn 100100 4 #define LL long long 5 6 int Phi[maxn],divisor[maxn],f[maxn]; 7 int n,a,t,top; 8 LL ans; 9 10 void FindPhi() 11 { 12 int t,m; 13 Phi[1]=1; 14 for (int i=2;i<maxn;i++) 15 { 16 Phi[i]=i-1; 17 t=(int) sqrt(i); 18 for (int j=2;j<=t;j++) 19 { 20 m=i; 21 while (m%j==0) m/=j; 22 if (m==i) continue; 23 Phi[i]= (m==1)? i-i/j:Phi[m]*Phi[i/m]; 24 break; 25 } 26 } 27 } 28 29 int main() 30 { 31 FindPhi(); 32 scanf("%d",&n); 33 f[1]=1; 34 for (int j=0;j<=n;j++) 35 { 36 scanf("%d",&a); 37 top=0; 38 t=(int) sqrt(a); 39 for (int i=1;i<=t;i++) if (a%i==0) 40 { 41 divisor[++top]=i; 42 if (i!=a/i) divisor[++top]=a/i; 43 } 44 for (int i=1;i<=top;i++) if (!f[divisor[i]]) 45 { 46 ans+=Phi[divisor[i]]; 47 f[divisor[i]]=1; 48 } 49 } 50 printf("%I64d\n",ans); 51 return 0; 52 }