BZOJ3994: [SDOI2015]约数个数和(莫比乌斯反演)

Description

 设d(x)为x的约数个数,给定N、M,求  
 

Input

输入文件包含多组测试数据。

第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行两个整数N、M。

Output

 T行,每行一个整数,表示你所求的答案。

Sample Input

2
7 4
5 6

Sample Output

110
121

解题思路:

有一个喜闻乐见的结论:

${\sum_{i=1}^{n}}{\sum_{j=1}^{m}}{d(i*j)]}={\sum_{i=1}^{n}}{\sum_{j=1}^{m}}[gcd(i,j)==1]{\left \lfloor \frac{N}{i} \right \rfloor}{\left \lfloor \frac{M}{j} \right \rfloor}$

剩下的大家都会了吧QAQ

代码:

  1 #include<map>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 const int N=3000000;
  6 struct lnt{
  7     std::map<unsigned int,long long>Arr;
  8     long long arr[N];
  9     bool has[N];
 10     void Insert(unsigned int x,long long y)
 11     {
 12         if(x<N)
 13             arr[x]=y,has[x]=true;
 14         else
 15             Arr[x]=y;
 16     }
 17     bool find(unsigned int x)
 18     {
 19         if(x<N)
 20             return has[x];
 21         else
 22             return Arr.find(x)!=Arr.end();
 23     }
 24     long long val(unsigned int pos)
 25     {
 26         if(pos<N)
 27             return arr[pos];
 28         return Arr[pos];
 29     }
 30 };
 31 unsigned int prime[N];
 32 int phi[N];
 33 int miu[N];
 34 bool vis[N];
 35 unsigned int cnt;
 36 lnt Sum_phi;
 37 lnt Sum_miu;
 38 void gtp(void)
 39 {
 40     miu[1]=phi[1]=1;
 41     Sum_phi.Insert(0,0);
 42     Sum_miu.Insert(0,0);
 43     for(int i=2;i<N;i++)
 44     {
 45         if(!vis[i])
 46         {
 47             prime[++cnt]=i;
 48             miu[i]=-1;
 49             phi[i]=i-1;
 50         }
 51         for(int j=1;j<=cnt&&i*prime[j]<N;j++)
 52         {
 53             vis[i*prime[j]]=true;
 54             if(i%prime[j]==0)
 55             {
 56                 miu[i*prime[j]]=0;
 57                 phi[i*prime[j]]=phi[i]*prime[j];
 58                 break;
 59             }
 60             miu[i*prime[j]]=-miu[i];
 61             phi[i*prime[j]]=phi[i]*(prime[j]-1);
 62         }
 63     }
 64     for(int i=1;i<N;i++)
 65     {
 66         Sum_phi.Insert(i,Sum_phi.val(i-1)+phi[i]);
 67         Sum_miu.Insert(i,Sum_miu.val(i-1)+miu[i]);
 68     }
 69     return ;
 70 }
 71 long long PHI_search(unsigned int pos)
 72 {
 73     if(Sum_phi.find(pos))
 74         return Sum_phi.val(pos);
 75     long long tmp=0;
 76     for(unsigned int i=2,j;i<=pos;i=j+1)
 77     {
 78         j=pos/(pos/i);
 79         tmp+=PHI_search(pos/i)*(long long)(j-i+1);
 80     }
 81     Sum_phi.Insert(pos,1ll*pos*(pos+1)/2-tmp);
 82     return 1ll*pos*(pos+1)/2-tmp;
 83 }
 84 long long MIU_search(unsigned int pos)
 85 {
 86     if(Sum_miu.find(pos))
 87         return Sum_miu.val(pos);
 88     long long tmp=0;
 89     for(unsigned int i=2,j;i<=pos;i=j+1)
 90     {
 91         j=pos/(pos/i);
 92         tmp+=(j-i+1)*MIU_search(pos/i);
 93     }
 94     Sum_miu.Insert(pos,1-tmp);
 95     return 1-tmp;
 96 }
 97 int main()
 98 {
 99     gtp();
100     int T;
101     scanf("%d",&T);
102     while(T--)
103     {
104         int x;
105         scanf("%d",&x);
106         printf("%lld %lld\n",PHI_search(x),MIU_search(x));
107     }
108     return 0;
109 }

猜你喜欢

转载自www.cnblogs.com/blog-Dr-J/p/10162061.html