Newcoder 华华给月月出题(线筛)题解

题目描述:

华华刚刚帮月月完成了作业。为了展示自己的学习水平之高超,华华还给月月出了一道类似的题:
Ans=Ni=1(iNmod(109+7))Ans=⊕i=1N(iNmod(109+7))
⊕符号表示异或和,详见样例解释。
虽然月月写了个程序暴力的算出了答案,但是为了确保自己的答案没有错,希望你写个程序帮她验证一下。
1N1.3×107

输入描述:

输入一个正整数N。

输出描述:

输出答案Ans。

样例:

输入 2005117
输出 863466972

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

参考:线性筛法

思路:因为线筛复杂度O(n),直接线筛所有的x^n,然后异或和。

ps:原来我写了这么久的线性筛一直都是埃氏筛,埃氏筛复杂度大概O(n * sqrt n)跪了orz

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 13e6 + 10;
const ll MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
ll pmul(ll a, ll b){
    ll ret = 1;
    while(b){
        if(b & 1) ret = (ret * a) % MOD;
        b >>= 1;
        a = (a * a) % MOD;
    }
    return ret;
}
ll fac[maxn];
int prime[maxn], pn;
bool p[maxn];
void init(ll n){
    pn = 0;
    memset(p, false, sizeof(p));
    fac[1] = 1;
    for(int i = 2; i <= n; i++){
        if(!p[i]){
            p[i] = true;
            prime[pn++] = i;
            fac[i] = pmul(i, n);
        }
        for(int j = 0; j < pn && i * prime[j] <= n; j++){
            p[i * prime[j]] = true;
            fac[i * prime[j]] = fac[i] * fac[prime[j]] % MOD;
            if(i % prime[j] == 0) break;
        }
    }
}
int main(){
    ll n, ans = 0;
    scanf("%lld", &n);
    init(n);
    for(int i = 1; i <= n; i++){
        ans ^= fac[i];
    }
    printf("%lld", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/KirinSB/p/10507502.html