zoukankan      html  css  js  c++  java
  • "红色病毒"问题 HDU 2065 递推+找循环节

    题目连接:

    http://acm.hdu.edu.cn/showproblem.php?pid=2065

    递推类题目, 可以考虑用数学方法来做, 但是明显也可以有递推思维来理解。

    递推的话基本就是状态转移了, 如何找状态是递推的关键。

    我们把这个分为四个状态

    A 出现次数的奇偶和B出现状态的奇偶,我们可以构造出四个状态:

                              A        B

    第一个状态 :        偶       偶     0

    第二个状态 :        偶       奇     1

    第三个状态 :        奇       偶     2

    第四个状态 :        奇       奇     3

     我们由这些状态进行转移 设定数组  dp[第k个状态][字符串的长度n]

    进行状态转移:

    偶偶  <-    偶 奇  +  偶偶  + 奇偶    

    依次类推........

    dp[0][i] = (dp[0][i-1]*2 + dp[1][i-1] + dp[2][i-1]);
    dp[1][i] = (dp[1][i-1]*2 + dp[0][i-1] + dp[3][i-1]);
    dp[2][i] = (dp[2][i-1]*2 + dp[0][i-1] + dp[3][i-1]) ;
    dp[3][i] = (dp[3][i-1]*2 + dp[1][i-1] + dp[2][i-1]) ;

    得到四个状态转移方程

    dp[0][i-1]*2 是因为 无论是 第i个 字符是A  或者是 B 对下一个状态都 无影响。

    他们给我们的数字是非常大的, 因此我们要去找循环节。

    循环节是20个数字  一个循环, 但是前两个数字不在循环内部 要特殊处理

    下面是代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<stack>
     7 #include<string>
     8 #include<queue>
     9 using namespace std;
    10 const int maxn =  50;
    11 const long long INF =  0xfffffff;
    12 
    13 int main()
    14 {
    15     int dp[4][maxn] ={0};
    16     int P[maxn];
    17     dp[0][0] = 1;
    18     for(int i=1; i<=30; i++)
    19     {
    20         dp[0][i] = (dp[0][i-1]*2 + dp[1][i-1] + dp[2][i-1]) % 100;
    21         dp[1][i] = (dp[1][i-1]*2 + dp[0][i-1] + dp[3][i-1]) % 100;
    22         dp[2][i] = (dp[2][i-1]*2 + dp[0][i-1] + dp[3][i-1]) % 100;
    23         dp[3][i] = (dp[3][i-1]*2 + dp[1][i-1] + dp[2][i-1]) % 100;
    24      //   cout << dp[0][i] << endl;
    25         if(i > 2)
    26             P[i-3] =dp[0][i];
    27     }
    28     int T, cas;
    29 
    30     long long n;
    31     while(cin >> T, T)
    32     {
    33         cas = 1;
    34         while(T--)
    35         {
    36             cin >> n;
    37             cout << "Case "<<cas++<<": ";
    38 
    39             if(n < 3)
    40                 cout<<dp[0][n]<<endl;
    41             else
    42                 cout<<P[(n-3)%20]<<endl;
    43 
    44             if(!T)
    45                 cout << endl;
    46         }
    47     }
    48     return 0;
    49 }
  • 相关阅读:
    C#通过正则表达式统计词频的一个方法
    本地服务器远程连接其它数据库
    拼字符串成为时间,和两个计算时间点的中间值
    删除文件夹里的图片,打印删除日志
    行转列SQL语句
    加载出一个有层次的下拉框
    查询结果列传行
    【Java&Python双管齐下复健002】回文数和反转数
    【Java&Python双管齐下复健001】冒泡排序和质数判断
    【LeetCode记录】初级算法:数组之删除排序数组中的重复项
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4077171.html
Copyright © 2011-2022 走看看