博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《挑战程序设计竞赛》2.6 数学问题-素数 AOJ0009 POJ3126 3421 3292 3641
阅读量:5080 次
发布时间:2019-06-12

本文共 6542 字,大约阅读时间需要 21 分钟。

AOJ0009

题意

求不大于n的素数个数。

思路

素数筛法可解,筛法过程中可顺便统计不大于n的素数个数。

另外这个题由于有多个测试数据,可预先求出题目所给数据范围的所有解。
素数筛法中我的写法里要注意数的范围,这个题中的i*i是可能超过int表示范围的,因而我提交了好几次都是RE,需要提前判断。

代码

#include 
#include
#include
using namespace std;const int N = 1000000;bool prime[N];int num[N];int main(void){ fill(prime, prime+N, true); fill(num, num+N, 0); prime[1] = false; for (int i = 2; i < N; i ++) { num[i] = num[i-1]; if (prime[i]) { num[i] ++; if (i > (int)sqrt((double)N)) continue; for (int j = i*i; j < N; j += i) { prime[j] = false; } } } int n; while (scanf("%d", &n) != EOF) printf("%d\n", num[n]); return 0;}

POJ3126

题意

给定两个四位素数a b,要求把a变换到b。

变换的过程要保证每次变换出来的数都是一个四位素数,而且当前这步的变换所得的素数与前一步得到的素数只能有一个位不同,而且每步得到的素数都不能重复。

思路

这个题其实主要考的是BFS,素数判定只是其中的条件判定依据。此处的素数构造用的是素数筛法。

代码

Source CodeProblem: 3126       User: liangrx06Memory: 260K        Time: 16MSLanguage: C++       Result: AcceptedSource Code#include 
#include
#include
#include
using namespace std;const int N = 10000;const int INF = 10000;bool isPrime[N];void initPrime(){ for (int i = 0; i < N; i ++) isPrime[i] = true; for (int i = 2; i < N; i ++) { if (isPrime[i]) { for (int j = i*i; j < N; j += i) isPrime[j] = false; } }}int d[N];int exp10(int x){ int res = 1; while (x--) res *= 10; return res;}int BFS(int begin, int end){ int i, j; queue
q; for (i = 1000; i < N; i++) d[i] = INF; q.push(begin); d[begin] = 0; while( q.size() ) { int p = q.front(); q.pop(); if (p == end) break; for (i = 1; i <= 1000; i *= 10) { int m = (p/i) % 10; for (j = 0; j <= 9; j ++) { if (j == m) continue; if (j == 0 && i == 1000) continue; int n = p + (j-m) * i; if (isPrime[n] && d[n] == INF) { q.push(n); d[n] = d[p] + 1; } } } } return d[end];}int main(void){ int t, begin, end; initPrime(); cin >> t; while (t--) { cin >> begin >> end; int res = BFS(begin, end); if (res == INF) printf("Imossible\n"); else printf("%d\n", res); } return 0;}

POJ3421

题意

给你一个数X,将X分解成1~X的因子数列,前一个数可以整数后一个数,求满足条件的最大链长以及有多少条这样长的链。

思路

容易想到因式分解,最大链长就是素数因子个数,链的个数即是全部素因子的排列数。

若有m个素因子x1,x2,…,xm,每个素因子的个数为c1,c2,…,cm,素因子个数相加为C,则全部素因子排列数为:
C!/(c1!c2!***cm!)

代码

Source CodeProblem: 3421       User: liangrx06Memory: 208K        Time: 125MSLanguage: C++       Result: AcceptedSource Code#include 
#include
#include
#include
using namespace std;const int N = 1024;bool isPrime[N+1];void initPrime(){ int i, j; for (i = 0; i <= N; i ++) isPrime[i] = true; isPrime[0] = isPrime[1] = false; for (i = 2; i <= N; i ++) { if (isPrime[i]) { for (j = i*i; j <= N; j += i) isPrime[j] = false; } }}typedef long long LL;typedef pair
P;LL fact(int n){ LL res = 1; while (n > 1) { res *= n; n --; } return res;}P solve(int n){ int i, j; queue
q; for (i = 2; i <= N; i ++) { if (!isPrime[i]) continue; if (n % i == 0) { j = 0; while (n % i == 0) { n /= i; j ++; } q.push(j); if (n == 1) break; } } if (n > 1) q.push(1); P res = P(0, 1); while (q.size()) { int m = q.front(); q.pop(); res.first += m; res.second *= fact(m); } res.second = fact(res.first) / res.second; return res;}int main(void){ int n; initPrime(); while (cin >> n) { P res = solve(n); printf("%lld %lld\n", res.first, res.second); } return 0;}

POJ3292

题意

对于4*n+1(n为自然数)组成的集合,乘法在该集合中是封闭的。现规定h-prime是这个集合的数字中只有1和本身能整除的数(不含1)。其余为h合数。从h合数中划分出一部分数字,这些数是由两个h素数相乘得到的,称之为h-semi。现要求在指定1~n范围内有多少个h-semi。

思路

注意这里的素数区别于普通意义上的素数,要根据题目中给出的规则来判定。但求h-prime时仍可用素数筛法,求出h-prime后就可以以两两素数相乘的循环找出所有h-semi。

代码

Source CodeProblem: 3292       User: liangrx06Memory: 3136K       Time: 16MSLanguage: C++       Result: AcceptedSource Code#include 
#include
#include
using namespace std;const int N = 1000001;bool isPrime[N+1];bool isSemi[N+1];int countSemi[N/4+1];void initPrime(){ int i; for (i = 0; i <= N; i ++) isPrime[i] = true; isPrime[0] = isPrime[1] = false; for (i = 5; i <= N; i += 4) { if (isPrime[i]) { if (i > (int)sqrt((double)N)) continue; for (int j = i*i; j <= N; j += 4*i) isPrime[j] = false; } }}void initSemi(){ int i, j; for (i = 1; i <= N; i += 4) { isSemi[i] = false; countSemi[i/4] = 0; } for (i = 5; i <= N; i += 4) { if (i > (int)sqrt((double)N)) break; for (j = i; j <= N; j += 4) { if (i * j > N) break; if (isPrime[i] && isPrime[j]) isSemi[i * j] = true; } } for (i = 5; i <= N; i += 4) { countSemi[i/4] = countSemi[i/4-1]; if (isSemi[i]) countSemi[i/4] ++; }}int main(void){ int n; initPrime(); initSemi(); while (cin >> n && n) { printf("%d %d\n", n, countSemi[n/4]); } return 0;}

POJ3641

题意

判断p是否是基于a的伪素数。输入p,a,两个数如果p是素数输出no,如果p不是素数,判断a^p%p==a是否成立,如果成立输出yes,否则输出no。

思路

这个题在书中分类到快速幂运算里面了,显然分类错误,应该分类到素数

主要考察素数判定,这个题对时间复杂度要求不高,采用i从2到sqrt(n)能否整除n的方式就可以。

代码

Source CodeProblem: 3641       User: liangrx06Memory: 212K        Time: 16MSLanguage: C++       Result: AcceptedSource Code#include 
#include
#include
using namespace std;typedef long long LL;bool isPrime(LL n){ int i; for (i = 2; i <= (LL)sqrt(double(n)); i ++) { if (n % i == 0) return false; } return true;}int main(void){ LL a, p; while (cin >> p >> a) { if (!p && !a) break; if (isPrime(p)) { printf("no\n"); continue; } LL p0 = p, a0 = a; LL res = 1; while (p0) { if (p0 % 2 == 1) res = (res * a0) % p; a0 = (a0 * a0) % p; p0 /= 2; } if (res == a) printf("yes\n"); else printf("no\n"); } return 0;}

转载于:https://www.cnblogs.com/liangrx06/p/5083761.html

你可能感兴趣的文章
217. Contains Duplicate
查看>>
vue2.0 关于Vue实例的生命周期
查看>>
jenkins 更换主数据目录
查看>>
Silverlight中恼人的g.i.cs错误
查看>>
SQLite 数据库增删改查
查看>>
<s:iterator>的status
查看>>
C++入门--1.0输入输出
查看>>
让搭建在Github Pages上的Hexo博客可以被Google搜索到
查看>>
Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段...
查看>>
在WPF控件上添加Windows窗口式调整大小行为
查看>>
背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu
查看>>
HDU2665_Kth number
查看>>
持续集成 Jenkins +Gitlab + SSH 自动发布 HTML 代码
查看>>
二维数组中某列的求和
查看>>
BOM问题
查看>>
教育类APP开发现新增长,多款APP该如何突围?
查看>>
打开3389
查看>>
React学习记录
查看>>
nginx常见内部参数,错误总结
查看>>
对象与类
查看>>