这道题需要了解素数筛的原理,而不是只是套模板。
需要明白一点,我们在欧拉筛中筛掉合数用的是这个合数的最小值因子。还记得那一步if(i%primes[j]==0) break;吗?这一步就保证我们用的是最小值因子筛掉所有的合数。
我们可以这么理解,当i%primes[j]的时候,i=k*primes[j],这时候,我们如果不break,继续下一个,则i*primes[j+1]=k*priems[j]*primes[j+1]=(i*primes[j+1])*primes,说明现在的i*primes[j+1]的最小质因子其实是primes[j],只要后面i增大了,i*primes[j+1]自然会被筛掉。
对于这道题,我们只需要改下筛法,记录下最小值因子就行了。
相似题目:CF1047C
AC代码
#include <iostream> #include <map> #include <ctime> #include <vector> #include <climits> #include <algorithm> #include <random> #include <cstring> #include <cstdio> #include <map> #include <set> #include <bitset> #include <queue> #define inf 0x3f3f3f3f #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #define rep(i, a, n) for(register int i = a; i <= n; ++ i) #define per(i, a, n) for(register int i = n; i >= a; -- i) #define ONLINE_JUDGE using namespace std; typedef long long ll; const int mod=1e9+7; template<typename T>void write(T x) { if(x<0) { putchar('-'); x=-x; } if(x>9) { write(x/10); } putchar(x%10+'0'); } template<typename T> void read(T &x) { x = 0;char ch = getchar();ll f = 1; while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();} while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f; } ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} ll lcm(ll a,ll b){return a/gcd(a,b)*b;}; ll ksm(ll a,ll n){//看是否要mod ll ans=1; while(n){ if(n&1) ans=(ans*a)%mod; a=a*a%mod; n>>=1; } return ans%mod; } //============================================================== const int maxn=3e7+10; int n; int primes[maxn],tot; int vis[maxn]; int fac[maxn]; void init(){ for(int i=2;i<maxn;i++){ if(!vis[i]) primes[tot++]=i,fac[i]=i; for(int j=0;j<tot&&primes[j]*i<maxn;j++){ fac[i*primes[j]]=primes[j]; vis[i*primes[j]]=1; if(i%primes[j]==0) break; } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif //=========================================================== read(n); init(); int ans=0; /*rep(i,1,10){ cerr<<fac[i]<<" "; } cerr<<endl;*/ rep(i,1,n) ans+=fac[i]/*,cerr<<fac[i]<<endl*/; write(ans); //=========================================================== return 0; }