hdu 6134

来源:互联网 发布:怎么在淘宝上传图片 编辑:程序博客网 时间:2024/06/06 03:01

题目链接:点击打开链接


题解思路:F[i]表示累加j∈(1-i)[向上取整的i/j],f[i]则表示累加的[向下取整的[i/j],[i/j]表示向上取整,(i/j)表示向下取整,那么你会发现[i/j] = ((i-1)/j) + 1,那么F[i] = f[i-1] + i;

f[i] = F[i] -i+(i的因子个数)。那么我们最后在应用容斥可得,容斥用莫比乌斯就行了,例如将公约数是2的删去,那么假设n是12,将所有1-12的数能整除2的除以2得到1,2,3,4,5,6那么不就相当于是F[6]了吗,所以减去F[6]相当于减去公约数为2的GCD和,然后容斥一下就可以了。


代码:

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <queue>#include <set>#include <map>#include <string>#include <math.h>using namespace std;const int mx = 1e6+10,mod = 1e9+7,N = 1e3+10;typedef long long ll;int n,m,pri[mx],F[mx],f[mx],mu[mx],val[mx];bool vis[mx];void init(){    int top = 0;    F[1] = f[1] = 1;    for(int i=2;i<mx;i++){        if(!vis[i]) pri[top++] = i,mu[i] = -1;        for(int j=0;j<top&&pri[j]*i<mx;j++){            vis[i*pri[j]] = 1;            if(i%pri[j]==0){                mu[i*pri[j]] = 0;                break;            }            mu[i*pri[j]] = -mu[i];        }    }    for(int i=2;i<mx;i++){        int ret = 1,po = i, sq = sqrt(i);        for(int j=0;j<top&&pri[j]<=sq;j++){            if(po%pri[j]==0){                int cnt = 0;                while(po%pri[j]==0) cnt++, po /= pri[j];                ret = ret * (cnt+1);            }            if(po==1) break;        }        val[i] = ret;        if(po!=1) val[i] *= 2;    }    for(int i=2;i<mx;i++){        F[i] = (f[i-1] + i)%mod;        f[i] = (F[i] - i + val[i]+mod)%mod;    }    for(int i=2;i<mx;i++) f[i] = F[i];    for(int i=2;i<mx;i++) if(mu[i])        for(int j=i;j<mx;j+=i)        F[j] += mu[i]*f[j/i];    for(int i=2;i<mx;i++) F[i] = (F[i]+F[i-1])%mod;}int main(){    init();    while(~scanf("%d",&n)) printf("%d\n",F[n]);    return 0;}