huntian oy(杜教筛 欧拉函数)

original link - http://acm.hdu.edu.cn/showproblem.php?pid=6706

题意:

f ( n , a , b ) = ∑ i = 1 n ∑ j = 1 i g c d ( i a − j a , i b − j b ) [ g c d ( i , j ) = 1 ] % ( 1 0 9 + 7 ) f(n,a,b)=\sum_{i=1}^n \sum_{j=1}^i gcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\%(10^9+7) f(n,a,b)=i=1nj=1igcd(iaja,ibjb)[gcd(i,j)=1]%(109+7)

解析:

由于 a , b a,b a,b互质,所以有 g c d ( i a − j a , i b − j b ) = i − j gcd(i^a-j^a,i^b-j^b)=i-j gcd(iaja,ibjb)=ij

f ( n , a , b ) = ∑ i = 1 n i ∗ ∑ j = 1 i [ g c d ( i , j ) = 1 ] − ∑ i = 1 n ∑ j = 1 i j [ g c d ( i , j ) = 1 ] f(n,a,b)=\sum_{i=1}^n i*\sum_{j=1}^i[gcd(i,j)=1]-\sum_{i=1}^n \sum_{j=1}^ij[gcd(i,j)=1] f(n,a,b)=i=1nij=1i[gcd(i,j)=1]i=1nj=1ij[gcd(i,j)=1]

f ( n , a , b ) = ∑ i = 1 n i ∗ ϕ ( i ) − ∑ i = 1 n i ∗ ϕ ( i ) − [ i = 1 ] 2 f(n,a,b)=\sum_{i=1}^n i*\phi(i)-\sum_{i=1}^n \dfrac{i*\phi(i)-[i=1]}{2} f(n,a,b)=i=1niϕ(i)i=1n2iϕ(i)[i=1]

f ( n , a , b ) = ∑ i = 1 n i ∗ ϕ ( i ) − 1 2 f(n,a,b)=\dfrac{\sum_{i=1}^ni*\phi(i)-1}{2} f(n,a,b)=2i=1niϕ(i)1

F ( n ) = i ∗ ϕ ( i ) ,    A n s ( n ) = ∑ i = 1 n i ∗ ϕ ( i ) ,    g ( i ) = i F(n)=i*\phi(i),\;Ans(n)=\sum_{i=1}^ni*\phi(i),\;g(i)=i F(n)=iϕ(i),Ans(n)=i=1niϕ(i),g(i)=i

可以推得:

A n s ( n ) = ∑ i = 1 n ( F ∗ g ) ( i ) − ∑ d = 2 n g ( d ) A n s ( n / d ) g ( 1 ) Ans(n)=\dfrac{\sum_{i=1}^{n}(F*g)(i)-\sum_{d=2}^{n}g(d)Ans(n/d)}{g(1)} Ans(n)=g(1)i=1n(Fg)(i)d=2ng(d)Ans(n/d)

其中:
∑ i = 1 n ( F ∗ g ) ( i ) = ∑ i = 1 n ∑ d ∣ i F ( d ) ∗ g ( i d ) = ∑ i = 1 n ∑ d ∣ i i ∗ ϕ ( d ) = ∑ i = 1 n i 2 \sum_{i=1}^{n}(F*g)(i)=\sum_{i=1}^{n}\sum_{d|i}F(d)*g(\frac{i}{d})=\sum_{i=1}^{n}\sum_{d|i}i*\phi(d)=\sum_{i=1}^ni^2 i=1n(Fg)(i)=i=1ndiF(d)g(di)=i=1ndiiϕ(d)=i=1ni2

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2019-08-25-15.37.26
 */
#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<
const LL mod=1e9+7;
const int maxn=1e6+9;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
/*_________________________________________________________head*/

LL Pow(LL a,LL b,LL mod){
    LL res=1;
    while(b>0){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

int pri[maxn],now,phi[maxn];
bool vis[maxn];

void init(){
    phi[1]=1;
    rep(i,2,maxn-1){
        if(!vis[i]){
            pri[++now]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=now&&pri[j]*i<maxn;j++){
            vis[pri[j]*i]=1;
            if(i%pri[j]==0){
                phi[pri[j]*i]=phi[i]*pri[j];
                break;
            }
            phi[pri[j]*i]=phi[i]*(pri[j]-1);
        }
    }
}

LL Pre[maxn];
LL _2,_6;
unordered_map<int,LL>Map;
LL Ans(LL n){
    if(n<maxn)return Pre[n];
    if(Map.count(n))return Map[n];
    LL res = 1ll*n*(n+1)%mod*(2*n+1)%mod*_6%mod;
    for(LL l=2,r;l<=n;l=r+1){
        r=n/(n/l);
        res-=(l+r)*(r-l+1)/2%mod*Ans(n/l)%mod;
    }
    return Map[n]=res%mod;
}

int main(){
    init();
    rep(i,1,maxn-1){
        Pre[i]=(Pre[i-1]+1ll*i*phi[i])%mod;
    }
    int t=rd();
    _2=Pow(2,mod-2,mod);
    _6=Pow(6,mod-2,mod);
    while(t--){
        int n=rd(),a=rd(),b=rd();
        printf("%lld\n",(Ans(n)-1+mod)%mod*_2%mod);
    }
    return 0;
}

你可能感兴趣的:(数论/数学,例题)