hdu5382 GCD?LCM! 推公式+埃式筛法

来源:互联网 发布:jsonobject转java对象 编辑:程序博客网 时间:2024/06/06 04:37

题意:计算S(n)mod 258280327.其中[exp],exp是一个逻辑表达式,如果exp为真,[exp]=1,否则[exp]=0;

         case<=10^5, n<=10^6

F(n)=i=1nj=1n [ lcm(i,j)+gcd(i,j)n ]S(n)=i=1nF(i)
分析:case数很大, 直接递推打表计算S(1~n).

         F(n)=F(n1)+(2n1) - T(n-1)

         T(n)= G(n/d-1)   (其中d为n的约数)

         G(n)= [gcd(d,n/d)=1]=2^k (k为n的质因子个数)

         用筛法 O(nlogn)预处理即可.


#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <vector>#include <map>#include <tr1/unordered_map>#define clr(x, y) memset(x, y, sizeof x)using namespace std;typedef long long LL;const double eps=1e-8;const int maxn=1000100;const int mod=258280327;int valid[maxn];LL G[maxn],T[maxn],F[maxn],S[maxn];void init(){    for(int i=0;i<maxn;i++)    {        G[i]=valid[i]=1;        T[i]=0;    }    G[0]=0;    for(int i=2;i<maxn;i++)    {        if(valid[i])        {            for(int j=i;j<maxn;j+=i)            {                G[j]=G[j]*2%mod;                valid[j]=0;            }        }    }    for(int i=1;i<maxn;i++)    {        for(int j=i;j<maxn;j+=i)        {            T[j]=(T[j]+G[j/i-1])%mod;        }    }    F[1]=S[1]=1;    for(int i=2;i<maxn;i++)    {        F[i]=(((F[i-1]+2*i-1)%mod-T[i-1])%mod+mod)%mod;        S[i]=(S[i-1]+F[i])%mod;    }}int main(){   // freopen("input.txt","r",stdin);    init();    int t,n;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        printf("%I64d\n",S[n]);    }    return 0;}


0 0