Problem A:NEFU586 纯素数
每一位单独处理出来
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
int cnt=0, max1=1e6, prime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
{
prime[++cnt] = i;
}
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
bool judge(int k)
{
int wei[7], len=0;
fill(wei, wei+7, 0);
while(k)
{
wei[len++] = k%10;
k /= 10;
}
for(int i=0; i<len; i++)
{
int tmp=0;
for(int j=i; j>=0; j--) tmp = tmp*10+wei[j];
if(!flag[tmp]) return 0;
}
return 1;
}
int main()
{
ios::sync_with_stdio(false);
int n;
init();
while(~scanf("%d", &n))
{
if(judge(n)) printf("YES\n");
else printf("NO\n");
}
return 0;
}
Problem B:NEFU587 半素数
当i是n的因子时,可同时判断n/i。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+1;
int cnt=0, max1=1e7, prime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
prime[++cnt] = i;
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
bool judge(int k)
{
for(int i=2; i*i<=k; i++)
if(!(k%i) && flag[i] && flag[k/i]) return true;
return false;
}
int main()
{
init();
int n;
while(~scanf("%d", &n))
{
if(judge(n)) printf("YES\n");
else printf("NO\n");
}
return 0;
}
Problem C:NEFU825 函数版素数判定
此题使用cin,cout会超时(反正我是)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+1;
int cnt=0, max1=1e7, prime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
prime[++cnt] = i;
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
bool judge(int n)
{
bool flag = 1;
for(int i=1; prime[i]<=sqrt(n); i++)
if(n%prime[i]==0)
{
flag = 0;
break;
}
if(n==1) flag=0;
return flag;
}
int main()
{
//ios::sync_with_stdio(false);
int n;
init();
while(~scanf("%d", &n))
{
if(judge(n)) printf("YES\n");
else printf("NO\n");
}
return 0;
}
Problem D:NEFU585 最大素因子
与模板相比可额外申请一个数组用来存该数的下标(与prime正好相反)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
int cnt=0, max1=1e6, prime[maxn], reprime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
{
cnt++;
prime[cnt] = i;
//cout<<cnt<<endl;
//return;
reprime[i] = cnt;
//cout<<cnt<<" "<<i<<endl;
}
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
int query(int k)
{
if(k==1) return 0;
if(k==2) return 1;
//cout<<flag[5]<<" "<<prime[5]<<" "<<reprime[5]<<endl;
for(int i=k; i>=2; i--)
if(k%i==0 && flag[i])
{
//cout<<"i"<<i<<endl;
return reprime[i];
}
}
int main()
{
ios::sync_with_stdio(false);
int n;
init();
while(cin>>n)
{
cout<<query(n)<<endl;
}
//cout<<flag[max1]<<endl;
return 0;
}
Problem E:NEFU781 素数与数论
存储下标方式与D题相同,此时不能直接使用x和y进行reprime[x]
和reprime[y]
的操作,而应先是x和y自增或自减至区间内首尾素数。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
int cnt=0, max1=1e6, prime[maxn], reprime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
{
cnt++;
prime[cnt] = i;
reprime[i] = cnt;
}
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
int x, y;
init();
while(cin>>x>>y)
{
while(!flag[x]) x++;
while(!flag[y]) y--;
// 直到x和y分别为范围内的最小和最大素数
cout<<reprime[y]-reprime[x]+1<<endl;
}
return 0;
}
Problem F:NEFU1321 差点是素数
用二分来做。注意区间是否重复,如重复需要进行合并。
也听说了能用前缀和做。
就差那么两分钟就能交上了,哎呀可惜。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+1, maxdata=1e12;
int t;
ll l1, r1, l2, r2;
ll cnt=0, tot=0, prime[maxn], ans[maxn];
bool flag[maxn];
void init() // 线性素数筛
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(ll i=2; i<maxn; i++)
{
if(flag[i])
{
prime[++cnt] = i;
}
for(ll j=1; j<=cnt&&prime[j]*i<=maxn; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
void getanswer() // 得到满足条件的数
{
for(ll i=1; i<=cnt; i++)
for(ll j=prime[i]*prime[i]; j<=maxdata; j*=prime[i])
ans[tot++] = j;
sort(ans, ans+tot);
}
ll getans(ll L, ll R)
{
ll r = upper_bound(ans, ans+tot, R)-ans; // 上限
ll l = lower_bound(ans, ans+tot, L)-ans; // 下限
return r-l;
}
int main()
{
ios::sync_with_stdio(false);
init(); // 执行线性素数筛
getanswer(); // 得到满足条件的数
cin>>t;
while(t--)
{
cin>>l1>>r1>>l2>>r2; // 注意区间重合情况
if(l1>r2 || r1<l2) // 区间不重合
{
ll rans = getans(l1, r1)+getans(l2, r2); // 加起来算
cout<<rans<<endl;
}
else // 区间重合
{
ll rans = getans(min(l1, l2), max(r1, r2)); // 合并区间
cout<<rans<<endl;
}
}
return 0;
}
Problem G:NEFU1669 高木同学的因子
数据没有加强,直接用gcd可以水过。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll x, y;
cin>>x>>y;
int m = __gcd(x, y);
int cnt=0;
for(int i=1; i*i<=m; i++)
if(m%i==0) cnt++;
if(sqrt(m)*sqrt(m) == m) cout<<cnt*2-1<<endl;
else cout<<cnt*2<<endl;
return 0;
}
这里有唯一分解定理版本@nefu马老三:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#include <iomanip>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
int fx(int n)
{
int ans = 1;
for (int i = 2; i * i <= n; i++)
{
int a = 0;
while (n % i == 0)
{
a++;
n /= i;
}
ans *= (a + 1);
}
if (n > 1)
ans *= 2;
return ans;
}
int main()
{
ll x, y;
scanf("%lld%lld", &x, &y);
int n = __gcd(x, y);
printf("%d\n", fx(n));
return 0;
}
Problem H:NEFU1704 知否知否,应是绿肥红瘦
模板题,注意数据范围。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+1;
int cnt=0, max1=1e7, prime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
prime[++cnt] = i;
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
bool judge(long long n)
{
bool flag = 1;
for(int i=1; prime[i]<=sqrt(n); i++)
if(n%prime[i]==0)
{
flag = 0;
break;
}
if(n==1) flag=0;
return flag;
}
int main()
{
ios::sync_with_stdio(false);
int n;
long long x, y, z;
init();
cin>>n;
while(n--)
{
cin>>x>>y>>z;
if(judge(x+y-z)) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}
Problem I:NEFU2113 素数线性筛
相同题目:洛谷P3383 【模板】线性筛素数
扫描二维码关注公众号,回复:
9279344 查看本文章
模板题。
#include<bits/stdc++.h>
using namespace std;
const int maxn=4e7+1;
int cnt=0, prime[maxn];
bool flag[maxn];
void init(int max1)
{
fill(flag, flag+max1+1, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
prime[++cnt] = i;
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
int n, q, k;
cin>>n>>q;
init(n);
while(q--)
{
cin>>k;
cout<<prime[k]<<endl;
}
return 0;
}
Problem J:NEFU1262 五十弦翻塞外声
套用唯一分解定理的求因子和,不过错了亿次而已。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
int cnt=0, max1=1e6, prime[maxn];
bool flag[maxn];
void init()
{
fill(flag, flag+maxn, 1);
flag[0]=0;
flag[1]=0;
for(int i=2; i<=max1; i++)
{
if(flag[i])
{
prime[++cnt] = i;
}
for(int j=1; j<=cnt&&prime[j]*i<=max1; j++)
{
flag[prime[j]*i] = 0;
if(!(i%prime[j])) break;
}
}
}
int cas, b[100010];
long long tot=1;
void factor(int n)
{
//cas=0;
tot=1;
//memset(a, 0, sizeof(a));
//memset(b, 0, sizeof(b));
for(int i=1; i<=cnt && prime[i]*prime[i]<=n; i++)
{
int s=1;
while(!(n%prime[i]))
{
//b[cas]++;
n /= prime[i];
s *= prime[i];
}
tot = tot * (s*prime[i]-1) / (prime[i]-1);
//if(b[cas]) cas++;
}
if(n > 1)
tot *= (n+1);
// b[cas] = 1;
}
int main()
{
ios::sync_with_stdio(false);
init();
int t, n;
cin>>t;
while(t--)
{
cin>>n;
factor(n);
// for(int i=0; i<cas; i++)
// cout<<b[i]<<" ";
cout<<tot<<endl;
}
return 0;
}