原题链接:传送门
Description
outputstandard output
You are given an integer number n. The following algorithm is applied to it:
1.if n=0, then end algorithm;
2.find the smallest prime divisor d of n;
3.subtract d from n and go to step 1.
Determine the number of subtrations the algorithm will make.
Input
The only line contains a single integer n (2≤n≤1010).
Output
Print a single integer — the number of subtractions the algorithm will make.
Examples
Input
5
Output
1
Input
4
Output
2
Note
In the first example 5 is the smallest prime divisor, thus it gets subtracted right away to make a 0.
In the second example 2 is the smallest prime divisor at both steps.
题意:给你一个整数 n,找到 n 的最小素因子 d,然后 n - d,并让步数加 1 .当 n = 0 时,结束.
思路: 暴力的话肯定超时,仔细想想会发现:
当 n 是2的倍数时,让n一直减2,步数即为为 n/2.
当 n 是个素数时,直接减去其本身,步数为 1.
当 n 既不符合 1) 也不符合 2) 时,可以让n先减其最小素因子,当到了 1) 或 2) 的情况时,就可以直接求出结果
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+1;
ll book[N];
ll prime[N];
ll Count = 0;
ll cnt = 0;
int flag = 0;
void GetPrime(){ //素数打表,求一部分素数
memset(book,0,sizeof(book));
for(ll i=2;i<N;i++){
if(book[i] == 0)
prime[cnt++] = i;
for(ll j=0;j<cnt;j++){
if(i*prime[j] > N)
break;
book[i*prime[j]] = 1;
if(i % prime[j] == 0)
break;
}
}
}
bool isprime(ll n){ //判断素数
double n_sqrt = double(sqrt((double)n));
if(n==2 || n==3)
return 1;
if(n%6!=1 && n%6!=5)
return 0;
for(int i=5;i<=n_sqrt;i+=6)
if(n%(i)==0 | n%(i+2)==0)
return 0;
return 1;
}
ll check(ll n){
if(n%2 == 0){ // 条件 1)
flag = 1;
return n/2;
}
else if(isprime(n)){ // 条件 2)
flag = 1;
return 1;
}
else return 0;
}
int main(){
ll n;
GetPrime();
scanf("%lld",&n);
ll ans = check(n);
for(ll i=0;i<cnt;i++){
if(n % prime[i] == 0){
if(flag) //当 满足 1) 或 2)时,直接结束
break;
n -= prime[i];
ans += 1;
ans += check(n);
}
}
printf("%lld\n", ans);
return 0;
}