牛客- 华华给月月出题(素数筛+快速幂)

题目链接

题意:

在这里插入图片描述
n<=1.3*10^7。

题解:
一开始还以为是个模板题,直接用快速幂去求,但是tle了。看了题解才知道,要先筛素数。
因为每个数都可以表示成一些质数相乘,所以我们对于某个合数x,可以表示成 x=x的最小质因子*y。那么x^n= x的最小质因子^n * y^n。那么在素数筛的过程就我们就可以求出所有元素的n次方。这样做可以减少使用快速幂的次数,大大降低了复杂度。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=13e6+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int prime[MAXN];
bool is_prime[MAXN];
ll fac[MAXN];
ll fastpow(ll a, ll b) //快速幂
{
    
    
    ll ans = 1;
    while (b)
    {
    
    
        if (b & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans;
}
void solve(int n)
{
    
    
    fac[1]=1;
    int p=0;
    for(int i=2;i<=n;i++)
    {
    
    
        is_prime[i]=true;
    }
    is_prime[0]=is_prime[1]=false;
    for(int i=2;i<=n;i++)
    {
    
    
        if(is_prime[i])
        {
    
    
            prime[p++]=i;
            fac[i]=fastpow(i,n);
        }
        for(int j=0;j<p&&i*prime[j]<=n;j++)
        {
    
    
            is_prime[i*prime[j]]=false;
            fac[i*prime[j]]=fac[i]*fac[prime[j]]%mod;
            if(i%prime[j]==0) break;
        }
    }
}
int main()
{
    
    
    int n;
    cin>>n;
    solve(n);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
    
    
        ans=ans^fac[i];
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/113488197