[HDU 2065][dp]"红色病毒"问题

来源:互联网 发布:app文件上传java 接口 编辑:程序博客网 时间:2024/04/28 12:17

“红色病毒”问题

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7414 Accepted Submission(s): 3064

Problem Description

医学界发现的新病毒因其蔓延速度和Internet上传播的”红色病毒”不相上下,被称为”红色病毒”,经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶,腺嘧啶均是成对出现的。
现在有一长度为N的字符串,满足一下条件:
(1) 字符串仅由A,B,C,D四个字母组成;
(2) A出现偶数次(也可以不出现);
(3) C出现偶数次(也可以不出现);
计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据肯能非常庞大,你只要给出最后两位数字即可.

Input

每组输入的第一行是一个整数T,表示测试实例的个数,下面是T行数据,每行一个整数N(1<=N<2^64),当T=0时结束.

Output

对于每个测试实例,输出字符串个数的最后两位,每组输出后跟一个空行.

Sample Input

4
1
4
20
11
3
14
24
6
0

Sample Output

Case 1: 2
Case 2: 72
Case 3: 32
Case 4: 0

Case 1: 56
Case 2: 72
Case 3: 56

Author
Rabbit

Source
RPG专场练习赛

Recommend
lcy | We have carefully selected several similar problems for you: 2062 2069 2070 2073 2077

题解

这道题给我第一感觉就是dp,写题卡的过程中在网上找题解,没发现用dp写的。这里就贴一份吧。
首先我们把状态分一下:
一、A和C均为偶数,这就是要求的。
二、A为偶数、C为奇数。
三、A为偶数、C为奇数。
四、A为奇数、C为奇数。
下面直接用序号①②③④代替以上状态。
开一个dp数组,第一维记为串长,第二维则标记以上状态。
则①对应dp[i][0],②dp[i][1],③dp[i][2], ④dp[i][3]。
如dp[i][0]表示串长为i,A C数量均为偶数的数量。
初始状态dp[1][0] = 2, dp[1][1] = 1, dp[1][2] = 1, dp[1][3] = 0;
再推导递推式

串长为i的①串,可以由串长为i - 1的①串在后面添加 “B” 或 “D”, 或者串长为i - 1的②串+ “C”, 或串长为i - 1的③串 + “A”得到。

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

串长为i的②串可以由串长为i-1的①串+ “C”,或②串 + “B” 或 “D”, 或④串 + “A”得到。

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

③串和②串相似

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

串长为i的④串可以由,串长为i - 1的②串 + “C” , ③串 + “A”,四串 + “B” 或 “D”。

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

递推完成。不过本题还有一些小细节需要处理,题目要求的是末两位数字。如果直接在递推过程对100取模,会导致结果错误,我采取的做法是对推过程对10000取模,最后输出答案时再对100取模。
同时,由于n范围为2^64,直接递推到n肯定会超时。而最终答案只包含两位,所以其具有周期性是显而易见,打表出来,找下周期就可以解决了。

//#define LOCAL#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <vector>#include <map>#include <set>#include <stack>#include <queue>#include <iostream>#include <cstdlib>#include <algorithm>using namespace std;#define LL long long#define ll long long#define INF 0x3f3f3f3f#define maxn MAX_N#define MOD mod#define MMT(x,i) memset(x,i,sizeof(x))#define REP(i, n) for(int i = 0; i < n; i++)#define FOR(i, n) for(int i = 1; i <= n; i++)#define pb push_back#define mp make_pair#define X first#define Y secondconst LL MOD = 1e9 + 7;const double pi = acos(-1.0);const double E = exp(1);const double EPS = 1e-8;const int MAX_N = 1000010;int dp[10010][4];int main(){  #ifdef LOCAL    freopen("in.txt", "r", stdin);    freopen("out.txt", "w", stdout);  #endif  ios::sync_with_stdio(false);  dp[0][0] = dp[0][1] = dp[0][2] = 1;  dp[1][0] = 2, dp[1][1] = dp[1][2] = 1, dp[1][3] = 0;  for(int i = 2; i <= 130; i++)  {    dp[i][0] = (dp[i - 1][0] * 2 + dp[i - 1][1] + dp[i - 1][2]) % 10000;    dp[i][1] = (dp[i - 1][0]  + dp[i - 1][1] * 2 + dp[i - 1][3]) % 10000;    dp[i][2] = (dp[i - 1][0]  + dp[i - 1][2] * 2 + dp[i - 1][3]) % 10000;    dp[i][3] = (dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][3] * 2) % 10000;//    cout << i << " " << dp[i][0] % 100 << endl;  }  int T;  while(cin >> T)  {    if(T == 0)  break;    for(int cas = 1; cas <= T; cas++)    {      long long n;      cin >> n;      int ans = 0;      if(n <= 11) ans = dp[n][0];      else  ans = dp[(n - 11) % (ll)20 + 11][0];      cout << "Case " << cas <<": " << ans % 100<< endl;    }    cout << endl;  }  return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 家养的小鸡打架怎么办 小鸡关在一起打架怎么办 小孩感冒出汗多怎么办 宝宝感冒出汗了怎么办 出汗多怎么办%3f 孩子睡觉出汗多怎么办 三年级孩子成绩下滑怎么办 幼儿数学不开窍怎么办 孩子一年级学习跟不上怎么办 孩子学习不认真怎么办 孩子平时不细心怎么办? 脖子出现黑圈怎么办 简历留白太多怎么办 excel数字外面加个圈怎么办 电脑输入法数字数不上怎么办 大班教案迷路了怎么办 迷路了怎么办活动反思 头突然眩晕是怎么办 孩子学习拖拉懒惰怎么办 头发晕想睡觉怎么办 五年级错别字多怎么办 入党志愿书写错字怎么办 高中不会写作文怎么办 考试不会写作文怎么办 高考不会写作文怎么办 孩子总是写错字怎么办 小孩总是写错字怎么办 孩子马虎不认真怎么办 小孩计算老出错怎么办 小学生计算总出错怎么办 高中考试总粗心怎么办 孩子考试总是粗心怎么办 一年级孩子考试粗心怎么办 老师说孩子粗心怎么办 计算题总出错怎么办 计算题总是出错怎么办 数学老是计算错误怎么办? 苗木抵扣计算错误怎么办 表格中计算错误怎么办 孩子电视瘾太大怎么办 孩子考试前失眠怎么办