首页 > 代码库 > 2016CCPC 合肥--最大公约数//每一年通向它的路上,多少人折戟沉沙,多少人功败垂成,有人一战成名,有人从头再来。

2016CCPC 合肥--最大公约数//每一年通向它的路上,多少人折戟沉沙,多少人功败垂成,有人一战成名,有人从头再来。

有这样一个有关最大公约数的函数:
函数 f(x, y):


{
c=0
当 y>0:
{
c +=1
t = x % y
x = y
y = t
}
返回 c * x * x
}


给出三个正整数n,m,p,你需要计算:

技术分享

 

i=1nj=1m?i?jf(i,j)

对p取模的结果。

技术分享
 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <stack>
 4 #include <algorithm>
 5 #include <cstring>
 6 #include <vector>
 7 #include <cmath>
 8 #include <cctype>
 9 using namespace std;
10 typedef long long ll;
11 void in(int& n){scanf("%d",&n);}
12 void in(ll& n){scanf("%I64d",&n);}
13 const int N = 700;
14 int gcd[N][N],num[N][N];
15 int n,m,p;
16 ll calc(ll x,ll y,ll tot,ll cnt)//tot 个数 cnt  分母
17 {
18     ll ans = (tot+1)*(x*y)+(tot+1)*tot/2*(y*y);//总和
19     ll rd = y*y%cnt;
20     ll ra = y*x%cnt;
21     ll res = 0; //余数
22     /*for(int i=0;i<=tot;++i){res+=(i*rd+ra)%cnt;}
23     return (ans-res)/cnt%p;
24     */ //复杂度太高
25     for(int i=0;i<cnt;++i){
26         res += (rd*i+ra)%cnt;
27     }
28     res = tot/cnt*res;
29     for(int i=0;i<=tot%cnt;++i)
30     {
31         res += (rd*i+ra)%cnt;
32     }
33     return  (ans-res)/cnt%p;
34 }
35 void init()
36 {
37     for(int i=0;i<N;i++)
38         for(int j=0;j<N;j++)
39             if(i==0||j==0) gcd[i][j]=i+j;
40             else if(i<j) gcd[i][j] = gcd[i][j%i];
41                  else gcd[i][j] = gcd[i%j][j];
42     for(int i=1;i<N;i++)
43         for(int j=0;j<i;j++)
44         {
45             if(j==0) num[i][j] = 1;
46             else num[i][j] = num[j][i%j] +1;
47         }
48 }
49 int main()
50 {
51     init();
52     int T;
53     scanf("%d",&T);
54     while(T--)
55     {
56         int ans = 0;
57         scanf("%d%d%d",&n,&m,&p);
58         for(int i=1;i<=m;i++)
59             for(int j=0;j<i&&j<=n;j++)
60             {
61                 ans+=calc(j/gcd[i][j],i/gcd[i][j],(n-j)/i,num[i][j]);
62                 ans%=p;
63             }
64         printf("%d\n",ans);
65     }
66     return 0;
67 }
AC代码

因为计算被m限制  变成了m个等差数列   求数列每一项/cnt 之和

但是  但是  裸计算余数复杂度太大 

所以    就是现场  看懂了题。。。也A不掉。。。。然后贴的这个余数 转化为cnt的计算方式。。。

肯定是以cnt长度为循环。。。tot/cnt个循环 
余下的tot%cnt 再求一次即可

那么复杂度就降下来了

 

2016CCPC 合肥--最大公约数//每一年通向它的路上,多少人折戟沉沙,多少人功败垂成,有人一战成名,有人从头再来。