「luogu3768」简单的数学题

莫比乌斯函数+杜教筛

注意n*n就会爆long long 写程序时要格外小心。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=5000010;
 5 int lim=5000000,p[N],tot;
 6 ll n,sum[N],inv2,inv6,mod,phi[N];
 7 map<ll,ll>hs;
 8 bool isp[N];
 9 ll qpow(ll x,ll y){
10     ll res=1;
11     while(y){
12         if(y&1) res=res*x%mod;
13         x=x*x%mod,y>>=1;
14     }
15     return res;
16 }
17 void pre(){
18     phi[1]=1;
19     for(int i=2;i<=lim;i++){
20         if(!isp[i]) p[++tot]=i,phi[i]=(i-1)%mod;
21         for(int j=1;j<=tot&&1LL*i*p[j]<=lim;j++){
22             isp[i*p[j]]=1;
23             if(i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1)%mod;
24             else{phi[i*p[j]]=phi[i]*p[j]%mod;break;}
25         }
26     }
27     for(int i=1;i<=lim;i++) sum[i]=(sum[i-1]+phi[i]*i%mod*i)%mod;
28     return;
29 }
30 inline ll calc(ll k){
31     k%=mod;
32     return k*(k+1)%mod*(2*k+1)%mod*inv6%mod;
33 }
34 ll getsum(ll k){
35     if(k<=lim) return sum[k];
36     if(hs[k]) return hs[k];
37     ll l=2,r,temp=(k+1)%mod*k%mod*inv2%mod,res=temp*temp%mod;
38     while(l<=k){
39         r=k/(k/l);
40         res=((res-(calc(r)-calc(l-1))%mod*getsum(k/l)%mod)%mod+mod)%mod;
41         l=r+1;
42     }
43     return hs[k]=res;
44 }
45 int main(){
46     scanf("%lld%lld",&mod,&n);
47     pre();
48     inv6=qpow(6,mod-2),inv2=qpow(2,mod-2);
49     ll l=1,r,ans=0;
50     while(l<=n){
51         r=n/(n/l);
52         ll temp=(n/l%mod)*(n/l%mod+1)%mod*inv2%mod;
53         ans=((ans+temp*temp%mod*((getsum(r)-getsum(l-1))%mod+mod)%mod)%mod+mod)%mod;
54         l=r+1;
55     }
56     ans=(ans+mod)%mod;
57     printf("%lld",ans);
58     return 0;
59 }

 

posted @ 2018-03-15 21:21  Cupcake  阅读(168)  评论(0编辑  收藏  举报