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