DZY Loves Math IV

来源:互联网 发布:mac能做什么 编辑:程序博客网 时间:2024/05/12 20:31

Description

给定n,m,求ni=1mj=1φ(ij)mod 1e9+7
n<=100,000,m<=1,000,000,000

定义sum(n,m)表示mi=1φ(in)

令z(n)表示和n含有的质因子相同且指数都为1的数
则有sum(n,m)=n/z(n)*sum(z(n),m)
那么现在只需考虑n的质因子指数都为1的情况。
若素数p|n则有sum(n,m)=(p-1)*sum(n/p,m)+sum(n,m/p)
然后递归边界用杜教筛计算就好了。

代码

#include<cstring>#include<algorithm>#include<cmath>#include<cstdio>#define fo(i,a,b) for(i=a;i<=b;i++)#define ll long longusing namespace std;const int maxn=1000000;const int mo=1000000000+7;const int m1=1000007;int c[maxn/2],fi[maxn+1],z[maxn+1],z1[maxn+1],i,j,n,m,ans;int h1[m1],h2[m1],w1[m1],w2[m1][2],s2[maxn];bool bz[maxn+1];int ha(int n){    int y=n%m1;    while (w1[y]!=0&&w1[y]!=n) y=(y+1)%m1;    return y;}int ss(int n){    if (n<=maxn) return fi[n];    int j=ha(n);if (w1[j]!=0) return h1[j];w1[j]=n;    int s=(ll)n*(n+1)/2%mo,i=1;    while (i<n) {        i++;int l=n/(n/i)-i;        s=(s-(ll)(l+1)*ss(n/i)%mo)%mo,i+=l;    }     return h1[j]=s;}int sum(int n,int m){    if (m==0) return 0;    if (n==1) return ss(m);    return ((ll)(z[n]-1)*sum(n/z[n],m)%mo+sum(n,m/z[n]))%mo;}int main(){    z1[1]=fi[1]=1;    fo(i,2,maxn) {        if (!bz[i]) c[++c[0]]=i,z1[i]=z[i]=i,fi[i]=i-1;        fo(j,1,c[0]) {            if (i>maxn/c[j]) break;            bz[i*c[j]]=1;            z[i*c[j]]=c[j];            if (i%c[j]==0){                z1[i*c[j]]=z1[i];                fi[i*c[j]]=fi[i]*c[j];                break;            }z1[i*c[j]]=z1[i]*c[j];            fi[i*c[j]]=fi[i]*fi[c[j]];        }    }    fo(i,2,maxn) (fi[i]+=fi[i-1])%=mo;    scanf("%d%d",&n,&m);    fo(i,1,n) {        int q=z1[i];if (s2[q]==0) s2[q]=sum(q,m);        ans=(ans+(ll)(i/q)*s2[q]%mo)%mo;    }    printf("%d\n",(ans%mo+mo)%mo);}
0 0