《挑战程序设计竞赛》2.6 数学问题-素数 AOJ0009 POJ3126 3421 3292 3641
AOJ0009
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0009
题意
求不大于n的素数个数。
思路
素数筛法可解,筛法过程中可顺便统计不大于n的素数个数。
另外这个题由于有多个测试数据,可预先求出题目所给数据范围的所有解。
素数筛法中我的写法里要注意数的范围,这个题中的i*i是可能超过int表示范围的,因而我提交了好几次都是RE,需要提前判断。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
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
http://poj.org/problem?id=3126
题意
给定两个四位素数a b,要求把a变换到b。
变换的过程要保证每次变换出来的数都是一个四位素数,而且当前这步的变换所得的素数与前一步得到的素数只能有一个位不同,而且每步得到的素数都不能重复。
思路
这个题其实主要考的是BFS,素数判定只是其中的条件判定依据。此处的素数构造用的是素数筛法。
代码
Source Code
Problem: 3126 User: liangrx06
Memory: 260K Time: 16MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
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 <int> 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
http://poj.org/problem?id=3421
题意
给你一个数X,将X分解成1~X的因子数列,前一个数可以整数后一个数,求满足条件的最大链长以及有多少条这样长的链。
思路
容易想到因式分解,最大链长就是素数因子个数,链的个数即是全部素因子的排列数。
若有m个素因子x1,x2,…,xm,每个素因子的个数为c1,c2,…,cm,素因子个数相加为C,则全部素因子排列数为:
C!/(c1!c2!***cm!)
代码
Source Code
Problem: 3421 User: liangrx06
Memory: 208K Time: 125MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
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<LL, LL> P;
LL fact(int n)
{
LL res = 1;
while (n > 1) {
res *= n;
n --;
}
return res;
}
P solve(int n)
{
int i, j;
queue<int> 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
http://poj.org/problem?id=3292
题意
对于4*n+1(n为自然数)组成的集合,乘法在该集合中是封闭的。现规定h-prime是这个集合的数字中只有1和本身能整除的数(不含1)。其余为h合数。从h合数中划分出一部分数字,这些数是由两个h素数相乘得到的,称之为h-semi。现要求在指定1~n范围内有多少个h-semi。
思路
注意这里的素数区别于普通意义上的素数,要根据题目中给出的规则来判定。但求h-prime时仍可用素数筛法,求出h-prime后就可以以两两素数相乘的循环找出所有h-semi。
代码
Source Code
Problem: 3292 User: liangrx06
Memory: 3136K Time: 16MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <cmath>
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
http://poj.org/problem?id=3641
题意
判断p是否是基于a的伪素数。输入p,a,两个数如果p是素数输出no,如果p不是素数,判断a^p%p==a是否成立,如果成立输出yes,否则输出no。
思路
这个题在书中分类到快速幂运算里面了,显然分类错误,应该分类到素数。
主要考察素数判定,这个题对时间复杂度要求不高,采用i从2到sqrt(n)能否整除n的方式就可以。
代码
Source Code
Problem: 3641 User: liangrx06
Memory: 212K Time: 16MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <cmath>
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;
}
《挑战程序设计竞赛》2.6 数学问题-素数 AOJ0009 POJ3126 3421 3292 3641的更多相关文章
- Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题
King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...
- 《挑战程序设计竞赛》2.3 动态规划-优化递推 POJ1742 3046 3181
POJ1742 http://poj.org/problem?id=1742 题意 有n种面额的硬币,面额个数分别为Ai.Ci,求最多能搭配出几种不超过m的金额? 思路 据说这是传说中的男人8题呢,对 ...
- 挑战程序设计竞赛》P345 观看计划
<挑战程序设计竞赛>P345 观看计划 题意:一周一共有M个单位的时间.一共有N部动画在每周si时 ...
- POJ 2386 Lake Counting 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=2386 <挑战程序设计竞赛>习题 题目描述Description Due to recent rains, water has ...
- poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=3253 题解 本题是<挑战程序设计>一书的例题 根据树中描述 所有切割的代价 可以形成一颗二叉树 而最后的代价总和是与子节点和深 ...
- 《挑战程序设计竞赛》2.6 数学问题-快速幂运算 POJ1995
POJ3641 此题应归类为素数. POJ1995 http://poj.org/problem?id=1995 题意 求(A1^B1+A2^B2+ - +AH^BH)mod M. 思路 标准快速幂运 ...
- 《挑战程序设计竞赛》2.6 数学问题-辗转相除法 AOJ0005 POJ2429 1930(1)
AOJ0005 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0005 题意 给定两个数,求其最大公约数GCD以及最小公倍数LCM. ...
- 《挑战程序设计竞赛》 4.1.1 矩阵 P286
想写几篇挑战的感悟,也有助于自己理解这本书.但这上面大多贴的是书上的代码,主要是为了用的时候后直接复制就好了,这样就很方便了,就相当于黑盒模板了. 1.线性方程组 /** \brief 高斯消元法 * ...
- poj1182食物链_并查集_挑战程序设计竞赛例题
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 65534 Accepted: 19321 Description ...
随机推荐
- 王兴内部讲话:为什么中国To B企业都活得这么惨
本文节选自美团创始人王兴内部讲话.在讲话中,王兴罕见地分享了他对全球和中国宏观经济的理解,谈了他对 TO B 业务的深度思考.全文近 15000 字,干货非常多,值得你花时间阅读. 我们今天讲一下餐饮 ...
- AHM ---301重定向
使用amh.conf 或重新创建一个test.conf配置文件 .保存目录 /usr/local/nginx/conf/rewrite 例如跳到 www.shuaixingkeji.com if ($ ...
- 003实现字符串反转reverse
这个简单就直接代码了 //写代码翻转一个C风格的字符串. (C风格的意思是"abcd"须要用5个字符来表示,包括末尾的 结束字符) #include <stdio.h> ...
- PHPEXCEL在thinkphp中封装成类使用
PHPEXCEL在thinkphp中封装成类使用 标签: phpexcel导出导入thinkphp -- : 435人阅读 评论() 收藏 举报 分类: php() 版权声明:本文为博主原创文章,未经 ...
- poj 1182 食物链 并查集的又一个用法
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41584 Accepted: 12090 Descripti ...
- jquery 操作input radio 单选框
1.jquery选中单选框 2.jquery 取消单选框 3.判断是否选中 4.设置不可编辑
- PHP学习笔记(1)数组函数
1.数组的键值操作函数: $arr = array("小明" => 98, "小红" => 76, "小黑" => 66, ...
- linux学习笔记8--命令touch
linux的touch命令不常用,一般在使用make的时候可能会用到,用来修改文件时间戳,或者新建一个不存在的文件. touch命令有两个功能:一是用于把已存在文件的时间标签更新为系统当前的时间(默认 ...
- Excel函数sumproduct应用案例-多条件求和
作者:iamlaosong 越来越认为sumproduct这个函数实用,过去用sum组函数.改起来复制起来都麻烦,sumif在条件多的时候也认为不方便. 如今改用sumproduct函数,就简单多了. ...
- CSS border-style 属性查询
border-style 属性用于设置元素所有边框的样式,或者单独地为各边设置边框样式.只有当这个值不是 none 时边框才可能出现. none solid dotted dashed double ...