比较容易想到令f[x]表示gcd=x的方案数,令g[x]表示x|gcd的方案数。

  那么有$ g(d)=\sum_{d|n} f(n)$,根据莫比乌斯反演,有$f(d)=\sum_{d|n} g(n)*\mu (\frac{n}{d})$

  我一开始想的是算出g以后,倒序枚举 i ,然后枚举 i 的倍数,递推出所有的f[i]……

  因为g比较好算嘛……快速幂一下什么的……

  然而$10^9$直接吓傻我。

  Orz PoPoQQQ

  快速求出mu的前缀和,$10^9$也照样不虚,太神辣

 1 /**************************************************************
 2     Problem: 3930
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:4200 ms
 7     Memory:54024 kb
 8 ****************************************************************/
 9  
10 //BZOJ 3930
11 #include<cstdio>
12 #include<map>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 typedef long long LL;
23 inline int getint(){
24     int r=1,v=0; char ch=getchar();
25     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
26     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
27     return r*v;
28 }
29 const int N=1e7+1000,P=1e9+7;
30 const int INF=0x3f3f3f3f;
31 /*******************template********************/
32  
33 int mu[N],prime[1001001],tot;
34 bool check[N];
35 map<int,LL> mu_sum;
36 LL n,d,l,r;
37 void getmu(){
38     int n=10000000;
39     mu[1]=1;
40     F(i,2,n){
41         if (!check[i]){
42             mu[i]=-1;
43             prime[++tot]=i;
44         }
45         F(j,1,tot){
46             int k=i*prime[j];
47             if (k>n) break;
48             check[k]=1;
49             if (i%prime[j]) mu[k]=-mu[i];
50             else{
51                 mu[k]=0;
52                 break;
53             }
54         }
55     }
56     F(i,1,n) mu[i]+=mu[i-1];
57 }
58 LL Mu_sum(int x){
59     if (x<=10000000) return mu[x];
60     if (mu_sum.find(x)!=mu_sum.end())
61         return mu_sum[x];
62     LL i,last,re=1;
63     for(i=1;i<=x;i=last+1){
64         last=x/(x/i);
65         if (x/i-1)
66             re-=(Mu_sum(last)-Mu_sum(i-1))*(x/i-1);
67     }
68     return mu_sum[x]=re;
69 }
70 LL Pow(LL a,int b){
71     LL r=1;
72     for(;b;b>>=1,a=a*a%P) if (b&1) r=r*a%P;
73     return r;
74 }
75 LL solve(){
76     LL i,last,re=0;
77     for(i=1;i<=r;i=last+1){
78         last=min(r/(r/i),l/i?(l/(l/i)):INF);
79         re+=(Mu_sum(last)-Mu_sum(i-1))*Pow(r/i-l/i,n);
80         re%=P;
81     }
82     return (re%P+P)%P;
83 }
84 int main(){
85 #ifndef ONLINE_JUDGE
86     freopen("3930.in","r",stdin);
87     freopen("3930.out","w",stdout);
88 #endif
89     n=getint(); d=getint(); l=getint(); r=getint();
90     l=(l-1)/d; r=r/d;
91     getmu();
92     printf("%lld\n",solve());
93     return 0;
94 }
View Code

相关文章: