没有合适的资源?快使用搜索试试~ 我知道了~
ACM算法经典例题
需积分: 11 5 下载量 90 浏览量
2019-04-09
15:16:31
上传
评论 4
收藏 809KB PDF 举报
温馨提示
试读
79页
acm相关资料 有相关例题 讲解 等相关知识
资源推荐
资源详情
资源评论
一、数论
1: Wolf and Rabbit
描述
There is a hill with n holes around. The holes are signed from 0 to n-1.
A rabbit must hide in one of the holes. A wolf searches the rabbit in anticlockwise order. The first hole he get into
is the one signed with 0. Then he will get into the hole every m holes. For example, m=2 and n=6, the wolf will get into
the holes which are signed 0,2,4,0. If the rabbit hides in the hole which signed 1,3 or 5, she will survive. So we call
these holes the safe holes.
输入
The input starts with a positive integer P which indicates the number of test cases. Then on the following P lines,each
line consists 2 positive integer m and n(0 <m,n<2147483648).
输出
For each input m n, if safe holes exist, you should output "YES", else output "NO" in a single line.
样例输入
2
1 2
2 2
样例输出
NO
YES
翻译:
描述
一座山有 n 个洞,洞被标记为从 0 到 n-1 。兔子必须藏在一个洞中。狼会逆时针方向搜索兔子。狼一开始在洞 0,然后他会每 m个洞进
去一次。例如: m=2,n=6,狼就会依次进入洞 0 2 4 0 。如果兔子藏在 1 3 5 就安全。
输入
第一行一个数字 p,表示下面有 p 组测试数据,每组测试数据 2 个数 m n(0<m,n<2147483648)
输出
每组数据输出一行,如果存在安全洞穴,输出 "YES",否则输出 "NO"
思路 / 方法:你是不是觉得总是无法通过,看看下面的解析
假设有 n=6 个洞 0 1 2 3 4 5
当 m=4时,狼进的洞是 0 4 2 0 ,也就是形成了一个循环,永远也到不了其他洞穴
当 m=5时,狼进的洞是 0 5 4 3 2 1 0 ,这时所有的洞都遍历了一遍。
思考:当 m=4和 m=5时,到底有什么区别?
当 n 和 m有公约数 (非 1) 时,就会形成一个数字个数小于 n 的循环
当 n 和 m无公约数时,就会形成一个数字个数为 n 的循环,此时没有安全洞穴。
解题关键:这题就转化成了判断两个数是否有公约数。
代码:
#include <iostream>
using namespace std;
long long greatestCommonDivisor(long long a, long long b)// 最大公约数
{
long long t;
while(b)
{
t = a % b;
a = b;
b = t;
}
return a;
}
int main()
{
int i, p;
long long m, n;
cin >> p;
for(i = 0; i < p; i++)
{
cin >> m >> n;
if(greatestCommonDivisor(m, n) == 1)// 公约数为 1 说明互斥,没有安全洞穴
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
2: a^b
描述
给定 a 和 b,输出 a^b 的最后一个数字。
输入
输入数据有多组,每组数据占一行,每行为 a 和 b 的值( 0<a,b<=2^30 )
输出
对每组输入数据,输出 a^b 的最后一位数字,每组数据占一行。
样例输入
2 2
3 4
样例输出
4
1
思路 / 方法:如果你模拟 a^b 次肯定会超时,而且数字还会超出 Int 范围
题目说只要最后一个数字,回想一下小学时学的乘法过程,貌似乘数最后一位和前面的无关
我们大胆的尝试一下用 a 的个位代替 a,然后我们发现循环 b 次还是会超时, 这是我们要想办法减少循环的次数, 试一下是不是有周期
规律
这时我们来列举一下 2 的 n 次方的个位: 2 4 8 6 2 4 8 6
我们发现周期为 4,我们在试试 1-9 的 n 次方,发现周期都是 4,所以,我们可以用 b%4代替 b,需要注意的是,当 b%4==0时,我们需
要给他加上 4,不然就不循环了。
代码:
#include <stdio.h>
int main()
{
int a, b, i, t;
while(scanf("%d %d", &a, &b) != EOF)
{
b = b % 4;
if(b == 0)
b = 4;
a = a % 10;
t = 1;
for(i = 0; i < b; i++)
{
t = t * a;
t = t % 10;
}
printf("%d\n", t);
}
return 0;
}
3: 筛选法求素数
描述
请使用筛选法输出 [a, b] 之间的所有素数。
输入
输入数据有多组,每组数据占一行,每行 2 个正整数 a 和 b,其中 2<=a<=b<=1000000。
输出
每组数据按从小到大的顺序输出 [a, b] 中所有的素数,每行最多输出 10 个素数。每组数据之后空一行。
样例输入
2 3
2 50
样例输出
2 3
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47
思路 / 方法:这题测试的数据量很大,所以尽量少循环,尽量少判断,要非常精简才能通过。
1. 定义一个全局变量 short s[1000001];// 全局变量默认为 0
2. 把数组中下标为奇数的值改为 1,偶数不用改,因为除了 2,其他偶数都不是素数
s[2] = 1;//2 也是素数
for(i = 3; i < 1000001; i = i + 2)// 把奇数全部假设为素数
s[i] = 1;
3. 把素数的倍数挖掉,改为 0。( 从 2 开始到根号 1000000 之间的素数的倍数挖掉 )
for(i = 2; i < 1000; i++)// 小于根号 1000000
if(s[i])// 判断是否为素数,只有素数的倍数才挖掉
for(j = i * 2; j < 1000001; j = j + i)// 把 i 的倍数的值改成 0
s[j] = 0;
4. 最后一点是输出格式,每组之间一个空行,另外一行最多 10 个。定义一个变量来记录输出了多少个,达到十个就输出换行。具体看
代码。
代码:
#include <stdio.h>
short s[1000001];// 全局变量默认为 0
int main()
{
int t, a, b, i, j;
s[2] = 1;//2 也是素数
for(i = 3; i < 1000001; i = i + 2)// 把奇数全部假设为素数
s[i] = 1;
for(i = 2; i < 1000; i++)// 小于根号 1000000
if(s[i])
for(j = i * 2; j < 1000001; j = j + i)// 把 i 的倍数的值改成 0
s[j] = 0;
while(scanf("%d %d", &a, &b) != EOF)
{
t = 0;
for(i = a; i <= b; i++)
{
if(s[i])// 素数就输出
{
if(t)
if(t == 10)
{
printf("\n");
t = 0;
}
else
printf(" ");
t++;
printf("%d", i);
}
}
printf("\n\n");
}
return 0;
}
4: The ones to remain
描述
There are N soldiers standing in one line. They are marked from 1 to N, from right to left. And they are given a number
m. Then the soldiers numbered off, straight from the right-hand man. The one who reported a number that is the multiple
of m was kept in the line. Others have to leave the line. They continue doing this till the number of people in the line
is less than m. For example, if there are 10 soldiers, and m = 3. For the first time the soldiers who are marked 3, 6,
9 remain in the line. For the second time the soldier who is marked 9 remains in the line. Because the number of soldiers
in the line is less than m, so the soldier marked 9 was the only one to remain in the line.
Now we want to know who will be the ones to remain, can you tell us ?
输入
There are several test cases in the input. Each test cases is only one line, contains two integers n and m.(3 <= n <=
109, 2 <= m <= n). The input ends when n = 0 and m = 0.
输出
For each test case, output two lines. The first line contains one integer x, the number of soldiers to remain. The second
line contains x integers, the numbers marked on the soldiers who remain in the line. You should output them in increasing
order.
样例输入
10 3
8 3
0 0
样例输出
1
9
2
3 6
翻译:
描述
有 N 个士兵站在一行。他们被从右到左标记为 1 到 N。他们被给与了一个数字 m。然后士兵直接从右面报数。报的数是 m的倍数的留下
来,其他人离开。然后继续上述操作,直到人数少于 m。例如,有 10 个士兵, m=3。第一次士兵报数为 3 6 9 的留下,第二次士兵报数
为 9 的留下。
输入
有多组测试数据。每组一行两个数 n m(3 <= n <= 109, 2 <= m <= n) ,以 0 0 结束
输出
每组输出两行,第一行输出一个 x 表示留下来的士兵数量,第二行输出 x 个留下来的士兵的编号。
思路 / 方法:
这题用数组来存储士兵状态就会超时,所以我们需要更精简的算法,很明显可以看出这是道数学题,所以我们多举几个例子,看看是
否有规律。
m=2时
1 2
2
1 2 3
2
1 2 3 4
2 4
4
1 2 3 4 5 6
2 4 6
4
1 2 3 4 5 6 7 8
2 4 6 8
4 8
8
m=3时
1 2 3
3
1 2 3 4
3
1 2 3 4 5 6
3 6
1 2 3 4 5 6 7 8 9
3 6 9
9
由上面的几个例子可以看出关键是找到一个不大于 n 的最大的 m^x。比如 m=2的时候, 依次是 2^1 2^1 2^2 2^2 2^3 ,当 x 一样时,
他们的结果值一样,并且就是 m^x。
当 m=3时,依次是 3^1 3^1 3^1 3^2 ,不难发现, x 一样时,结果的第一个数一样是 m^x。
接下来要找出有多少个结果值, 比较 m=3时的前 3 组数据, 发现第三组第二个结果 6 是 3*2 且不大于 n=6,我们大胆推断 m的个数就是
不大于 n 的 3 的倍数的个数。然后我们继续举个例子检验一下推论。
1 2 3 4 5 6 7 8 9 10 11 12
剩余78页未读,继续阅读
资源评论
Dʀᴇᴀ꯭M
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功