1. 程式人生 > >Luogu3768簡單的數學題

Luogu3768簡單的數學題

n) bubuko 題目 成了 除法 簡單 積性函數 isdigit style

題目描述

技術分享圖片

題解

我們在一通化簡上面的式子之後得到了這麽個東西。

技術分享圖片

前面的可以除法分塊做,後面的∑T2∑dµ(T/d)是積性函數,可以線性篩。

然後這個數據範圍好像不太支持線性篩,所以考慮杜教篩。

後面那個東西是個id*µ,恰好等於φ

所以我們求得東西就變成了i2φ

由於φ*I=id。所以我們令g(i)=i2,f(x)=i2φ,f*g=i3

於是這道題就做完了。

附:1^2+2^2+3^2+...+n^2=n*(n+1)*(2*n+1)/6,1^3+2^3+...+n^3=(1+2+3+..+n)^2

代碼

#include<iostream>
#include<cstdio>
#include<map>
#define N 5000009 
using namespace std;
typedef long long ll;
map<ll,ll>mp;
const int maxn=5000000;
ll mod,ans,inv2,inv6,k,phi[N],n;
int prime[N];
bool vis[N];
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    
while(!isdigit(c)){if(c==-)f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x; } inline ll power(ll x,ll y){ ll ans=1; while(y){if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;} return ans; } inline void prework(){ ll k; phi[
1]=1; for(int i=2;i<=maxn;++i){ if(!vis[i]){prime[++prime[0]]=i;phi[i]=i-1;} for(int j=1;j<=prime[0]&&(k=i*prime[j])<=maxn;++j){ vis[i*prime[j]]=1; if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;} else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } for(int i=1;i<=maxn;++i)phi[i]=(phi[i]*i%mod*i%mod+phi[i-1])%mod; } inline ll sum(ll x){return x%mod*(x+1)%mod*inv2%mod;} inline ll pf(ll x){return x%mod*x%mod;} inline ll pfsum(ll x){return x%mod*(x+1)%mod*(2*x%mod+1)%mod*inv6%mod;} ll get_phi(ll n){ if(n<=maxn)return phi[n]; if(mp.find(n)!=mp.end())return mp[n]; ll ans=pf(sum(n));ll r; for(ll l=2;l<=n;l=r+1){ r=n/(n/l); ll x=((pfsum(r)-pfsum(l-1))%mod+mod)%mod; ans=(ans-x*get_phi(n/l)%mod+mod)%mod; } return mp[n]=ans; } int main(){ mod=rd();n=rd(); inv2=power(2,mod-2);inv6=power(6,mod-2); prework(); ll l,r; for(l=1;l<=n;l=r+1){ r=n/(n/l); ans+=pf(sum(n/l))*(get_phi(r)-get_phi(l-1))%mod; ans=(ans%mod+mod)%mod; } cout<<ans; return 0; }

Luogu3768簡單的數學題