[原]携程预选赛A题-聪明的猴子-GCD+DP

时间:2023-03-09 22:31:20
[原]携程预选赛A题-聪明的猴子-GCD+DP

题目:

聪明的猴子



Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1123 Accepted Submission(s): 294





Problem Description

森林中有一排香蕉树(无限长),一只猴子站在其中一棵树上,猴子在跳跃前要先抽取一张卡片,卡片上写有A+1个自然数,其中最后一个是B,前A个数只能小于等于B,卡片上的数字可以相同。猴子每次跳跃先从卡片上任选一个自然数C,然后向左、或向右跳C棵树。猴子的任务是:跳到与它左边相邻的香蕉树上时,就可以吃掉上面的香蕉。



例如,当A=2,B=4时,对于卡片(2, 3, 4),猴子就可以吃到香蕉:它可以先向左跳3棵树,再向右跳两棵树。而对于卡片(2, 2, 4),猴子则怎么也不可能跳到它左边相邻的香蕉树上。



当确定A和B后,则一共可以有B^A张不同的卡片。问题是,在这所有的卡片中,有多少张可以让猴子完成任务。





Input

第1行k,表示有k组测试数据,k<=100

第2至k+1行,每行两个自然数A和B,以一个空格分开 (A<= 10 , B <= 20)。





Output

共k行,每行的数字代表每组数据中,可以让猴子跳到它左边相邻香蕉树的卡片数。





Sample Input

3

2 3

4 8

5 13





Sample Output

8

3840

371292

思路:(该题数据比较小) 对于B^A张卡片,只有卡片上的所有数字两两间的GCD == 1 的情况下,才可以让猴子吃到香蕉。由于求GCD运算满足交换律,所以这样考虑:卡片上一定有数字 B ,所以将只有一个数 B 的卡片看成初始状态,用dp(i,j)记录当在只有 B 一个数字的卡片上 加入 i 个数字(可以重复)的时候 GCD = j  时的可取卡片的数量。s 枚举所有数字,转移方程: dp( i,gcd( s, j ) )  +=  dp(i-1,j)。这样就可以重复利用前面的运算结果。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 30 int dp[maxn][maxn];
int gcd(int a, int b)
{
while(a)
{
int t = a;
a = b % a;
b = t;
}
return b;
} void test(int a, int b)
{
for(int i = 0; i <= a; i++)
{
for(int j = 0; j <= b; j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
}
int main()
{
int a, b;
while(scanf("%d%d",&a,&b) != EOF)
{
memset(dp, 0, sizeof(dp));
dp[0][b] = 1;
for(int i = 1; i <= a; i++)
for(int j = 1; j <= b; j++)
if(dp[i-1][j])
for(int s = 1; s <= b; s++)
dp[i][gcd(s,j)] += dp[i-1][j];
//test(a,b);
cout<<dp[a][1]<<endl;
}
}

这道题是poj 1091的改编,改小了数据。

作者:u011652573 发表于2014-4-11 13:08:23 原文链接
阅读:69 评论:0 查看评论