首页 > 代码库 > bzoj 1101 zap

bzoj 1101 zap

     gcd(x,y)=d-->gcd(x/d,y/d)=1。

      即求Σ(i<=n/d)Σ(j<=m/d) e(gcd(i,j))

      因为e=miu×1,可以卷积。

      因为多组询问,需要sqrt(n)计算。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define int long long
 6 using namespace std;
 7 int n,m;
 8 int pr[100005],su[100005],cnt,miu[100005];
 9 int sum[100005];
10 void shai()
11 {
12     miu[1]=1;
13     for(int i=2;i<=50000;i++)
14     {
15         if(!pr[i])su[++cnt]=i,pr[i]=i,miu[i]=-1;
16         for(int j=1;su[j]<=pr[i]&&su[j]*i<=100000&&j<=cnt;j++)
17         {
18               pr[su[j]*i]=su[j];
19               if(su[j]==pr[i])miu[su[j]*i]=0;
20               else miu[su[j]*i]=miu[i]*(-1);
21         }
22     }
23     for(int i=1;i<=50000;i++)sum[i]=sum[i-1]+miu[i];
24     return ;
25 }
26 signed main()
27 {
28    shai();
29    int cas;
30    scanf("%lld\n",&cas);
31    while(cas--)
32    {
33         int ans=0;
34         int n,m;int d;
35         scanf("%lld%lld%lld",&n,&m,&d);
36         n/=d;m/=d;if(n>m)swap(n,m);
37         int r;
38         for(int i=1;i<=n;i=r+1)
39         {
40             int y=n/i;int x=m/i;r=min(n/y,m/x);
41             ans+=(sum[r]-sum[i-1])*(x*y);
42      }
43      printf("%lld\n",ans);
44    }
45    return 0;
46 }

 

bzoj 1101 zap