[原]携程预选赛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 查看评论

转载于:https://www.cnblogs.com/ZiningTang/p/3834751.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值