去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了。
标签:const pac zoj 输出 printf char pos main iostream
去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了。
第一行一个整数n。
一行一个整数ans,表示答案模1000000007的值。
对于100%的数据n <= 10^9。
数学问题 莫比乌斯反演 脑洞题
$ans(n)=\sum_{i=1}^{n} \sum_{j=1}^{n} f(i,j)$
$=\sum_{i=1}^{n} \sum_{j=1}^{n} \sum_{k=1}^{n^2} [\frac{k}{gcd(i,j)}|j]$
(枚举gcd)
$=\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} [k|j][gcd(k,i)=1] $
(消掉j)
$=\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} d \lfloor \frac{n}{dk} \rfloor [gcd(k,i)=1] $
(约掉一个d)
$=\sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} \lfloor \frac{n}{k} \rfloor [gcd(k,i)=1] $
$=\sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} \lfloor \frac{n}{k} \rfloor \sum_{t|(ik)} \mu(t)$
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{dt} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{dt} \rfloor} \lfloor \frac{n}{kt} \rfloor$
(注意到i对后面没有影响,把求和变为乘)
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{n} \lfloor \frac{n}{dt} \rfloor\sum_{k=1}^{\lfloor \frac{n^2}{dt} \rfloor} \lfloor \frac{n}{kt} \rfloor$
(注意到d在大于$ \lfloor \frac{n}{t} \rfloor$ 时,后面全是0,所以缩小求和上界,后面的k同理)
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{dt} \rfloor\sum_{k=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{kt} \rfloor$
$= \sum_{t=1}^{1} \mu(t) (\sum_{d=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{dt} \rfloor)^2 $
$\mu$的前缀和可以用bzoj3944的方法筛出来,后面的平方项可以分块计算。
也就是说分块套分块就可以愉快地出解了。
隔壁Sfailsth告诉我可以直接用Bzoj3994的结论来做
↓也就是从这个式子开始:
$\sum_{i=1}^{N}\sum_{j=1}^{M}d(ij)=\sum_{i=1}^{N}\sum_{j=1}^{M}\lfloor\frac{N}{i}\rfloor\lfloor\frac{M}{j}\rfloor\lbrack gcd(i,j)=1 \rbrack $
确实很方便
(做完这道题之后,陪伴了我们一年的权限号过期了)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<map> 7 #define LL long long 8 using namespace std; 9 const int mod=1e9+7; 10 const int mxn=5000010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 14 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 15 return x*f; 16 } 17 int pri[mxn],mu[mxn],cnt=0; 18 bool vis[mxn]; 19 void init(){ 20 mu[1]=1; 21 for(int i=2;i<mxn;i++){ 22 if(!vis[i]){ 23 pri[++cnt]=i; 24 mu[i]=-1; 25 } 26 for(int j=1;j<=cnt && (LL)pri[j]*i<mxn;j++){ 27 int tmp=pri[j]*i; 28 vis[tmp]=1; 29 if(i%pri[j]==0){vis[tmp]=1;mu[tmp]=0;break;} 30 mu[tmp]=-mu[i]; 31 } 32 } 33 for(int i=2;i<mxn;i++){mu[i]=mu[i-1]+mu[i];} 34 return; 35 } 36 map<int,LL>mpmu; 37 int F(int x){ 38 if(x<mxn)return mu[x]; 39 if(mpmu.count(x))return mpmu[x]; 40 int res=1; 41 for(int i=2,pos;i<=x;i=pos+1){ 42 int y=x/i; 43 pos=x/y; 44 res=((LL)res-(LL)(pos-i+1)*F(y)%mod+mod)%mod; 45 } 46 mpmu[x]=res; 47 return res; 48 } 49 int calc(int x){ 50 int res=0; 51 for(int i=1,pos;i<=x;i=pos+1){ 52 int y=x/i; 53 pos=x/y; 54 res=(res+(pos-i+1)*(LL)y%mod)%mod; 55 } 56 return (LL)res*res%mod; 57 } 58 int main(){ 59 init(); 60 int n=read(); 61 LL ans=0; 62 for(int i=1,pos;i<=n;i=pos+1){ 63 int y=n/i;pos=n/y; 64 ans=((LL)ans+(((LL)F(pos)-F(i-1)%mod))*calc(y)%mod)%mod; 65 } 66 ans=(ans%mod+mod)%mod; 67 printf("%lld\n",ans); 68 return 0; 69 }
标签:const pac zoj 输出 printf char pos main iostream
原文地址:http://www.cnblogs.com/SilverNebula/p/6938283.html