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个“变化”,就可以做!
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }