《挑战程序设计竞赛》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 ...
随机推荐
- python list插入、拼接
1可以使用"+"号完成操作 输出为: [1, 2, 3, 8, 'google', 'com'] 2.使用extend方法 . 输入相同 3使用切片 输出相同 PS:len(l1) ...
- 【进程线程与同步】5.4 System.Threading.Interlocked 为多个线程共享的变量提供原子操作
using System; using System.Threading; internal class Program { private static long _counter = 1; pri ...
- SQL Server 保存不了修改后的表的解决方法
客户端报错(配图): 出现问题环境:在新建一个表之后,又想添加一个字段保存表,提示错误. 解决方案:在SQL Server 2008R2 中 对于对于重新保存新建表系统默认设置为“阻止”,在对应设置解 ...
- TypesMethodsAndFields
https://github.com/JesusFreke/smali/wiki/TypesMethodsAndFields Types dalvik's bytecode has two major ...
- flink on yarn 用户代码获取keytab本地文件和principal的方法
flink on yarn的情况下配置的keytab文件会根据每次yarn application 分配taskmanager的变化都是不一样的,在部分场景下用户代码也需要获得keytab文件在yar ...
- linux 从百度网盘下载文件的方法
linux 从百度网盘下载文件的方法 发表于2015 年 月 日由shenwang 方法1.wget wget是在Linux下开发的开放源代码的软件,作者是Hrvoje Niksic,后来被移植到包括 ...
- 【Objective-C】05-第一个OC的类
OC是一门面向对象的语言,因此它也有类.对象.静态\动态方法.成员变量的概念.这讲就来创建第一个OC的类. 一.语法简介 1.类 在Java中,我们用1个.java文件就可以描述清楚一个类:在OC中, ...
- php调用C代码的实现方法
在php程序中需要用到C代码,应该是下面两种情况: 1 已有C代码,在php程序中想直接用2 由于php的性能问题,需要用C来实现部分功能 针对第一种情况,最合适的方法是用system调用,把现有C代 ...
- Python中如何将字符串作为变量名
应用场景描述: 通过配置文件获取服务器上配置的服务名及运行端口号,编写python脚本检测服务上服务是否在运行? #!/usr/bin/env python # -*- coding:utf-8 -* ...
- Tuning 05 Sizing other SGA Structure
Redo Log Buffer Content The Oracle server processes copy redo entries from the user’s memory space t ...