ACM-ICPC 2018 南京賽區網絡預賽 - J. Sum (找規律+打表)
阿新 • • 發佈:2018-09-01
以及 pre 歐拉 name -i namespace c++ rime names
題意:\(f(i):i\)能拆分成兩個數的乘積,且要求這兩個數中各自都沒有出現超過1次的質因子。每次給出n,求\(\sum_{i=1}^{n}f(i)\)
分析:\(1 \le n \le 2e7\),每次查詢若都\(O(n)\)統計,肯定超時,必須打表。
類似打歐拉函數表的方式,對於數\(d\)以及素數\(p\),\(f(p)=2\);
當\(d|p\)時,若\(d|p^2\),則\(f(d*p^2)=0\);否則\(f(d*p)=f(d)/2\);
當\(d\dagger p\)時,\(f(d*p) = f(d)*2\)
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=2e7+5; bool vis[maxn]; int prime[maxn]; LL f[maxn]; LL res[maxn]; void init_f(int n){ int cnt=0; f[1]=1; for(int i=2;i<n;i++){ if(!vis[i]){ prime[cnt++]=i; f[i]=2; } for(int j=0;j<cnt&&i*prime[j]<n;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0){ if(i%(prime[j]*prime[j])==0) f[i*prime[j]]= 0; else f[i*prime[j]]= f[i]/2; break; } else{ f[i*prime[j]]= f[i]*2; } } } for(int i=1;i<maxn;++i) res[i] = res[i-1]+f[i]; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif init_f(maxn); int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); printf("%lld\n",res[n]); } return 0; }
ACM-ICPC 2018 南京賽區網絡預賽 - J. Sum (找規律+打表)