1. 程式人生 > >BZOJ3994: [SDOI2015]約數個數和(莫比烏斯反演)

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 }