牛客小白月赛12-C(欧拉筛解积性方程)

题目链接:https://ac.nowcoder.com/acm/contest/392/C

题意:给定n,求:

思路:令res[i]=i(%MOD),因为xn是一个积性函数,即(x*y)n=xn*yn,那么我们利用线性筛,在筛的过程对素数i直接通过快速幂计算res[i],对合数利用res[i*prime[j]]=res[i]*res[prime[j]]%MOD来解,prime[j]是能整除i*prime[j]的第一个素数。因为素数有n/logn个,快速幂为logn,所以复杂度为O(n)。

AC代码:

#include<cstdio>
using namespace std;
const int maxn=1e7+3e6+5;
const int MOD=1e9+7;
typedef long long LL;

bool vis[maxn];
LL n,prime[maxn],res[maxn];
int cnt,ans;

LL qpow(LL a,LL b){
    LL ret=1;
    while(b){
        if(b&1) ret=(ret*a)%MOD;
        a=(a*a)%MOD;
        b>>=1;
    }
    return ret;
}

void sieve(){
    res[1]=1;
    for(int i=2;i<=n;++i){
        if(!vis[i]){
            prime[cnt++]=i;
            res[i]=qpow(i,n);
        }
        for(int j=0;j<cnt&&i*prime[j]<=n;++j){
            vis[i*prime[j]]=true;
            res[i*prime[j]]=res[i]*res[prime[j]]%MOD;
            if(i%prime[j]==0) break;
        }
    }
}

int main(){
    scanf("%lld",&n);
    sieve();
    for(int i=1;i<=n;++i)
        ans^=res[i];
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/FrankChen831X/p/10922810.html