线性素数筛 ACM-ICPC 2018 南京赛区网络预赛 J Sum
Posted suut
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性素数筛 ACM-ICPC 2018 南京赛区网络预赛 J Sum相关的知识,希望对你有一定的参考价值。
https://www.jisuanke.com/contest/1555?view=challenges
题意:
题解:写完都没发现是个积性函数233
想法就是对x分解质因数,f(x)就是2^k,其中k是x分解结果中次数为一的质因子个数。如果有某个次数大于等于3,f(x)==0;
这样明显会TLE
所以就想一个递推的方法。
于是魔改了一下线性筛。
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<ctime> #include<cmath> #include<algorithm> #include<iomanip> #include<queue> #include<map> #include<bitset> #include<stack> #include<vector> #include<set> using namespace std; #define MAXN 1010 #define MAXM 1010 #define INF 1000000000 #define MOD 1000000007 #define ll long long #define eps 5e-6 ll n, N; #define rep(i,t,n) for(int i =(t);i<=(n);++i) #define per(i,n,t) for(int i =(n);i>=(t);--i) #define mmm(a,b) memset(a,b,sizeof(a)) const int maxn=2e7+1e5; int num = 0; int vis[maxn], pri[maxn]; ll f[maxn]; ll s[maxn]; void init() { rep(i, 1, maxn)f[i] = 1; mmm(vis, 0); mmm(pri, 0); num = 0; } void getpri() { for ( ll i = 2; i<N; i++) { if (!vis[i])pri[++num] = i,f[i]=2; for ( ll j = 1; j <= num && pri[j] * i<N; j++) { vis[pri[j] * i] = 1; f[pri[j] * i] *= f[pri[j]]*f[i]; if (i%pri[j] == 0) { //二次方 f[pri[j] * i] /= 4; if (i%(pri[j] * pri[j]) == 0)f[pri[j] * i] = 0;//三次方以上 break; }//如果i遇到了自己最小的质因子就直接跳出 } } } int main() { int t; cin >> t; int x = maxn; N = maxn; init(); getpri(); s[1] = 1; rep(i, 2, x) { s[i] =s[i-1]+ f[i]; } while (t--) { cin >> n; cout << s[n]<< endl; } //cin >> t; return 0; } /* 1 8 20000000 2 5 8 */
以上是关于线性素数筛 ACM-ICPC 2018 南京赛区网络预赛 J Sum的主要内容,如果未能解决你的问题,请参考以下文章
ACM-ICPC 2018 南京赛区网络预赛 - J. Sum (找规律+打表)
ACM-ICPC 2018 南京赛区网络预赛 Magical Girl Haze 最短路