Codeforces Round #641 (Div. 2) A. Orac and Factors(思维/素筛思想)

传送门


这道题折磨了我挺长时间,首先不难看出解题思路,对于第一次我们只需加上 n n n的最小非 1 1 1因子,后面都是 2 2 2

思路一:直接从 2 − n 2-n 2n枚举所有的因子,碰到第一个直接加上然后break

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=1e6+10;

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t,n,k;
    cin>>t;
    //Prime();
    while(t--){
        cin>>n>>k;
        for(int i=2;i<=n;i++){
            if(n%i==0){
                n+=i;
                k--;
                break;
            }
        }
        ll ans=n;
        cout<<ans+2*k<<endl;
    }
    return 0;
}

思路二:剑走偏锋的我偏要觉得这个方法最优,预处理之后直接 O ( 1 ) O(1) O(1)查找,这一写不打紧,找出了一直没注意到的易错点,祸亦是福吧

首先我一开始这样写:

void init(){
    memset(f,0,sizeof(f));
	int m=sqrt(maxn+0.5);
	for(int i=2;i<m;i++){
		if(!f[i]){
            f[i]=i;
			for(int j=i*i;j<maxn;j+=i){
                if(!f[j]) f[j]=i;
			}
		}
	}
}

不仔细思考总感觉没有问题,但是我们需要的是最小因子,这种方法只能帮我们判断 m a x n maxn maxn范围内的数是否都是素数,合数的话当然都能求出,但是大于根号下 m a x max max的质数,其 f f f为0!,因此,我们必须将最外层的循环改为 m a x n maxn maxn

void init(){
    memset(f,0,sizeof(f));
	int m=sqrt(maxn+0.5);
	for(int i=2;i<maxn;i++){
		if(!f[i]){
            f[i]=i;
			for(int j=i*i;j<maxn;j+=i){
                if(!f[j]) f[j]=i;
			}
		}
	}
}

然而,意外出现了,在电脑上怎么都跑不动,我甚至有点怀疑埃氏筛法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)了。实在没办法去求助学长,原来是第二层循环出错了,因为之前的板子整理的紫书上的,所以我一直用 i ∗ i i*i ii和根号下 m a x n maxn maxn,但是在这个问题中,如果我们最外层遍历到 m a x n maxn maxn那么 i ∗ i i*i ii会爆 i n t int int,因此还是乖乖从 2 ∗ i 2*i 2i开始吧:

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=1e6+10;

int f[maxn];

void init(){
    memset(f,0,sizeof(f));
	for(int i=2;i<maxn;i++){
		if(!f[i]){
            f[i]=i;
			for(int j=2*i;j<maxn;j+=i){
                if(!f[j]) f[j]=i;
			}
		}
	}
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t,n,k;
    init();
    cin>>t;
    while(t--){
        cin>>n>>k;
        ll ans=n+f[n];
        cout<<ans+2*(k-1)<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值