[洛谷P4388] 付公主的矩形

18.09.09模拟赛T1。

一道数学题。

题目传送门

首先把对角线当成是某个点的移动轨迹,从左下到右上。

那么这个点每上升一个单位长度,就穿过一个格子。

每右移一个单位长度,也会穿过一个格子。

例外:穿过格点,会减少穿过的格子数。

初步的结论:R*C的矩形,对角线穿过的格子数N=R+C-gcd(R,C)。

那么我们只需算出这个方程的解的个数。

可以看出,R、C和gcd(R,C)都是gcd(R,C)的倍数。

那么N显然也是。

设N/gcd(R,C)=n,R/gcd(R,C)=r,C/gcd(R,C)=c。

方程两边同除gcd(R,C):n=r+c-1。

由欧几里得算法可得:gcd(n+1,r)=gcd(n+1-r,r)=gcd( (r+c-1) +1-r,r)=gcd(c,r)。

这时候r和c一定是互质的,假如它们有公因数,在除以gcd(R,C)时就会被除掉。

所以:gcd(r,c)=1。得:gcd(n+1,r)=1。

即:n+1与r互质,n是N得因数。

答案即为:

所以我们线性筛出从2到n+1的欧拉函数phi [ i ],挑出其中i-1是n的因数的,把它们的phi [ i ]加起来就行了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int n,cnt,ans;
 7 int pr[100000005];
 8 bool v[100000005];
 9 int phi[100000005];
10 
11 int main()
12 {
13     scanf("%d",&n);
14     for(int i=2;i<=n+1;i++)
15     {
16         if(!v[i])
17         {
18             pr[++cnt]=i;
19             phi[i]=i-1;
20         }
21         if(n%(i-1)==0)ans+=phi[i];
22         for(int j=1;(j<=cnt)&&(i*pr[j]<=n+1);j++)
23         {
24             v[i*pr[j]]=true;
25             if(i%pr[j]==0)
26             {
27                 phi[i*pr[j]]=phi[i]*pr[j];
28                 break;
29             }else
30             {
31                 phi[i*pr[j]]=phi[i]*phi[pr[j]];
32             }
33         }
34     }
35     printf("%d",(ans+1)/2);
36     return 0;
37 }

 

posted @ 2018-09-10 20:19  cervusky  阅读(140)  评论(0编辑  收藏  举报

Contact with me