Codeforces915G. Coprime Arrays

n<=2e6的数组,m<=2e6个询问,对1<=i<=m的每个i问:只用<=i的数字填进数组,有多少种方案使数组的总gcd=1.强制把每个询问的答案求出来。

比如说现在有个确定的i=t,然后看看答案怎么算先。先把所有情况加起来,然后除去gcd=2,3,4,5,……的,那直接统计有多少gcd=2,3,4,5的不方便,总可以统计有多少gcd是2的倍数的,3的倍数的,……,吧!这样的话丢掉了gcd为2的倍数,3的倍数的,等等6的倍数丢多了一次因为在2和3都算了,要减掉……就一个容斥,对应了各自的莫比乌斯函数。于是可以愉快的写出t的答案$f(t)=\sum_{i=1}^{t} \mu(i) (\frac{t}{i})^n$。

然后就看看t变成t+1时答案怎么变化,对一个k,他的$(\frac{t}{k})$只有在t是k的倍数时才会变化!而这个“变化”的总数,就是1-m中所有1-m的倍数的数量的总数,就是m+m/2+m/3+……,就是mlnm个“变化”,就可以做!

 1 #include<string.h>
 2 #include<stdlib.h>
 3 #include<stdio.h>
 4 #include<math.h>
 5 //#include<assert.h>
 6 #include<algorithm> 
 7 //#include<iostream>
 8 //#include<bitset>
 9 using namespace std;
10 
11 int n,m;
12 #define maxn 2000011
13 const int mod=1e9+7;
14 int miu[maxn],prime[maxn],lp=0,mi[maxn],small[maxn]; bool notprime[maxn];
15 
16 int powmod(int a,int b)
17 {
18     int ans=1;
19     while (b)
20     {
21         if (b&1) ans=1ll*ans*a%mod;
22         a=1ll*a*a%mod;
23         b>>=1;
24     }
25     return ans;
26 }
27 
28 void pre(int n)
29 {
30     miu[1]=1;
31     for (int i=2;i<=n;i++)
32     {
33         if (!notprime[i]) {prime[++lp]=i; miu[i]=-1; small[i]=i;}
34         for (int j=1;j<=lp && 1ll*prime[j]*i<=n;j++)
35         {
36             notprime[i*prime[j]]=1;
37             small[i*prime[j]]=prime[j];
38             if (i%prime[j]) miu[i*prime[j]]=-miu[i];
39             else {miu[i*prime[j]]=0; break;}
40         }
41     }
42 }
43 
44 int ans,fix,num[maxn];
45 int list[maxn],ci[maxn],ll;
46 void play(int x)
47 {
48     fix+=miu[x]*(mi[num[x]+1]-mi[num[x]]);
49     fix+=fix<0?mod:0,fix-=fix>=mod?mod:0;
50     num[x]++;
51 }
52 void dfs(int now,int cur)
53 {
54     if (cur>ll) {play(now); return;}
55     for (int i=0,tmp=1;i<=ci[cur];i++,tmp*=list[cur]) dfs(now*tmp,cur+1);
56 }
57 
58 void solve(int x)
59 {
60     ll=0;
61     for (int i=x;i>1;i/=small[i])
62     {
63         if (list[ll]!=small[i]) list[++ll]=small[i],ci[ll]=1;
64         else ci[ll]++;
65     }
66     dfs(1,1);
67 }
68     
69 int main()
70 {
71     scanf("%d%d",&n,&m); pre(m);
72     for (int i=1;i<=m;i++) mi[i]=powmod(i,n);
73     
74     ans=0; fix=0;
75     for (int i=1;i<=m;i++) solve(i),ans+=i^fix,ans-=ans>=mod?mod:0;
76     printf("%d\n",ans);
77     return 0;
78 }
View Code

 

posted @ 2018-01-15 09:43  Blue233333  阅读(450)  评论(0编辑  收藏  举报