【线性筛】ccpc黑龙江省赛 F

第一次vp省赛,只出了三题,很寄啊

题意:

思路:

题目一直在强调最小质因子,我们考虑边跑线性筛边求贡献

一、

对于第一种情况,即遇到的数是质数,贡献直接+1就好了

二、

对于第二种情况,即遇到的数是一个质数的幂次

通过迭代得到:f(p^k)=f(n)=p^(k/2)

三、

对于第三种情况,f(n)=p1^(k1/2)*(n/p1^k1)

那这种情况的贡献就是用p1除完n之后的值*p1^k1,p1^k2就转化成第二种情况

然后去考虑线性筛

1.质数的时候贡献+1

2.当i%prime[j]==0的时候,prime[j]不是i的最小质因子,因此n=i*prime[j]具有prime[j]的幂次,也有别的质因子,所以就对应了第三种情况

3.当i%prime[j]!=0的时候,此时prime[j]是i的最小质因子,同样也是第三种情况。因为是用最小质因子去筛的,因此最小质因子的指数k1=1,贡献就是 p1^(1/2)*(i*p1)/p1^1=i

Code:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int mxn=1e7+10;

int n,len=0;
i64 ans=1;
int prime[mxn],vis[mxn];
i64 ksm(int a,int b){
    i64 res=1;
    while(b){
        if(b&1) res=(res*a);
        a=(a*a);
        b>>=1;
    }
    return res;
}
void init(int n){
    for(int i=2;i<=n;i++){
        if(!vis[i]) prime[++len]=i,ans++;
        for(int j=1;i<=n/prime[j];j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0){
                i64 tmp=i*prime[j];
                int s=0;
                while(tmp%prime[j]==0) tmp/=prime[j],s++;
                ans+=tmp*ksm(prime[j],s/2);
                break;
            }
            ans+=i;
        }
    }
}
void solve(){
    cin>>n;
    init(n);
    cout<<ans<<
;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int __=1;//cin>>__;
    while(__--)solve();return 0;
}
第一次vp省赛,只出了三题,很寄啊 题意: 思路: 题目一直在强调最小质因子,我们考虑边跑线性筛边求贡献 一、 对于第一种情况,即遇到的数是质数,贡献直接+1就好了 二、 对于第二种情况,即遇到的数是一个质数的幂次 通过迭代得到:f(p^k)=f(n)=p^(k/2) 三、 对于第三种情况,f(n)=p1^(k1/2)*(n/p1^k1) 那这种情况的贡献就是用p1除完n之后的值*p1^k1,p1^k2就转化成第二种情况 然后去考虑线性筛 1.质数的时候贡献+1 2.当i%prime[j]==0的时候,prime[j]不是i的最小质因子,因此n=i*prime[j]具有prime[j]的幂次,也有别的质因子,所以就对应了第三种情况 3.当i%prime[j]!=0的时候,此时prime[j]是i的最小质因子,同样也是第三种情况。因为是用最小质因子去筛的,因此最小质因子的指数k1=1,贡献就是 p1^(1/2)*(i*p1)/p1^1=i Code: #include using namespace std; using i64 = long long; const int mxn=1e7+10; int n,len=0; i64 ans=1; int prime[mxn],vis[mxn]; i64 ksm(int a,int b){ i64 res=1; while(b){ if(b&1) res=(res*a); a=(a*a); b>>=1; } return res; } void init(int n){ for(int i=2;i<=n;i++){ if(!vis[i]) prime[++len]=i,ans++; for(int j=1;i<=n/prime[j];j++){ vis[i*prime[j]]=1; if(i%prime[j]==0){ i64 tmp=i*prime[j]; int s=0; while(tmp%prime[j]==0) tmp/=prime[j],s++; ans+=tmp*ksm(prime[j],s/2); break; } ans+=i; } } } void solve(){ cin>>n; init(n); cout< >__; while(__--)solve();return 0; }
经验分享 程序员 微信小程序 职场和发展