acm算法经典例题

2020-04-21 08:40

一、数论

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

For each input m n, if safe holes exist, you should output \样例输入 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

每组数据输出一行,如果存在安全洞穴,输出\,否则输出\

思路/方法:你是不是觉得总是无法通过,看看下面的解析 假设有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 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 << \ else

cout << \ } return 0; } 2: a^b 描述

给定a和b,输出a^b的最后一个数字。 输入

输入数据有多组,每组数据占一行,每行为a和b的值(0

对每组输入数据,输出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 int main() {

int a, b, i, t;

while(scanf(\ {

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(\ } 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

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(\ {

t = 0;

for(i = a; i <= b; i++) {

if(s[i])//素数就输出 { if(t)

if(t == 10) {

printf(\ t = 0; } else

printf(\ t++;

printf(\ } }

printf(\ } 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


acm算法经典例题.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:河南省豫东豫北十所名校2014届高中毕业班阶段性测试(六)英语试

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: