HDU6134Battlestation Operational

来源:互联网 发布:ubuntu 32位库 dpkg 编辑:程序博客网 时间:2024/06/06 18:20

题目链接

题意

​ 求解

f(n)=i=1nj=1nij[(i,j)=1]

其中

[(i,j)=1]={1,gcd(i,j)=10,others

分析

​ =-=又一道公式推论神题。。解法和题解不同,是从网上找的结论,推论过程自行搜索吧。对于向下取整存在公式

g(n)=i=1nj=1nij[(i,j)=1]

g(n)=i|nmu[ni](j=1id[j])

其中 mu[i] 为莫比乌斯函数, d[j] 表示数 j 约数的个数。

于是可以利用筛法求出 d[j] ,再求一次前缀和。然后再次用筛法求出 g[n] 。剩下的问题就是如何将 g[n] 转换为 f[n] 。容易发现,除了 j=1 的时候,其它必然都无法整除,即贡献为1。于是利用欧拉定理求出 <j 且和 j 互质数的个数即可获得f[n]

代码

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<queue>using namespace std;#define LL long long#define MAXN 1001000const int mod=1e9+7;int mu[MAXN];LL ans[MAXN];LL d[MAXN];int phi[MAXN];void getPhi(){    for(int i=1;i<MAXN;++i)        phi[i]=i;    for(int i=2;i<MAXN;++i)        if(phi[i]==i)            for(int j=i;j<MAXN;j+=i)                phi[j]=phi[j]/i*(i-1);}void getMu(){    for(int i=1;i<MAXN;++i){        int target=i == 1?1:0;        int delta=target-mu[i];        mu[i]=delta;        for(int j=i+i;j<MAXN;j+=i)            mu[j]+=delta;    }}void init(){    getPhi();    getMu();    for(int i=1;i<MAXN;++i)        for(int j=i;j<MAXN;j+=i)            d[j]++;    for(int i=1;i<MAXN;++i)        d[i]=(d[i]+d[i-1])%mod;    for(int i=1;i<MAXN;++i)        for(int j=i;j<MAXN;j+=i)            ans[j]=(ans[j]+mu[j/i]*d[i])%mod;    for(int i=1;i<MAXN;++i)        ans[i]=(ans[i]+phi[i]-1)%mod;    for(int i=2;i<MAXN;++i)        ans[i]=(ans[i]+ans[i-1])%mod;}int main(){    init();    int n;    while(~scanf("%d",&n)){        printf("%d\n",ans[n]);    }}
原创粉丝点击