HDU 5608 function(数论)

来源:互联网 发布:张氏短打淘宝 编辑:程序博客网 时间:2024/06/08 13:27

Description
这里写图片描述
Input
第一行一正整数T表示用例组数,每组用例占一行为一整数n(T<=300,n<=10^9,只有五组用例n>10^6)
Output
对于每组用例输出一个答案
Sample Input
1
3
Sample Output
2
Solution
这里写图片描述
Code

#include<cstdio>#include<iostream>#include<map>using namespace std;typedef long long ll;#define maxn 1111111#define mod 1000000007#define inv (mod+1)/3map<int,int>m;map<int,int>::iterator it;int ans[maxn];void init(){    for(int i=1;i<maxn;i++)ans[i]=1ll*(i-1)*(i-2)%mod;    for(int i=1;i<maxn;i++)        for(int j=2*i;j<maxn;j+=i)        {            ans[j]-=ans[i];            if(ans[j]<0)ans[j]+=mod;        }    for(int i=2;i<maxn;i++)    {        ans[i]+=ans[i-1];        if(ans[i]>=mod)ans[i]-=mod;    }}int solve(int n){    if(n<maxn)return ans[n];    it=m.find(n);    if(it!=m.end())return it->second;    int cnt=1ll*n*(n-1)%mod*(n-2)%mod*inv%mod;    for(int i=2,next;i<=n;i=next+1)    {        next=n/(n/i);        cnt-=1ll*(next-i+1)*solve(n/i)%mod;        if(cnt<0)cnt+=mod;    }    return m[n]=cnt;}int main(){    init();    int T,n;    scanf("%d",&T);    while(T--)    {        m.clear();        scanf("%d",&n);        printf("%d\n",solve(n));    }    return 0;}
0 0