杭电 2065 红病毒问题
这是在学习递推的过程中遇到的问题, 问题描述:
"红色病毒"问题
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2418 Accepted Submission(s): 1033
Problem Description
医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶,腺嘧啶均是成对出现的。
现在有一长度为N的字符串,满足一下条件:
(1) 字符串仅由A,B,C,D四个字母组成;
(2) A出现偶数次(也可以不出现);
(3) C出现偶数次(也可以不出现);
计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据肯能非常庞大,你只要给出最后两位数字即可.
现在有一长度为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
Recommend
lcy
递推方法分析:
这一题, 同错排问题有很大的相似之处, 我们站在最后一个字母放置的立场上去看待这个问题。 当我们放置最后一个的时候, 设放置方法为f(n, 0), 那么前一次放置的情况有4中, 分别为:
1. A,B均为偶数个数 用方程表示f(n-1, 0)
2. 只有A为偶数个数 f(n-1, 1)
3. 只有B为偶数个数 f(n-1, 2)
4. A,B均不为偶数个数 f(n-1, 3)
则有如下的关系
1. f(n, 0) = 2*f(n-1, 0) + f(n-1, 1) + f(n-1, 2);
2. f(n, 1) = f(n-1, 0) + 2*f(n-1, 1) + f(n-1,3)
3. f(n, 2) = f(n-1, 0) + 2*f(n-1, 2) + f(n-1, 3)
4. f(n, 3) = f(n-1, 1) + f(n-1, 2) + 2*f(n-1, 3)
这个关系式的具体含义, 请自己领悟。。。。。
得出这个关系式后, 我们会想到对其进行化简, 其实, 我在解决这一个问题的时候, 并没有对其化简, 只是用程序模拟这种关系, 然后, 找出循环的长度, 最后, 将循环的一个环节, 放在一个长度为25的数组之中。 具体见下面的代码:
下面这一个程序是为了将f(n,0)计算出来,然后,放进数组里面去。
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
int num[26] = {0, 2};
bool isEqual(int a, int b, int l)
{
for(int i = 1; i <= l; i++)
{
if(a == num[i-1] && b == num[i])
return true;
}
return false;
}
int main()
{
ifstream cin("2065.txt");
int T;
__int64 N;
int a1 , a2 = 2, b1 , b2 = 1, c1 , c2 = 1, d1 , d2 = 0, i;
a1 = a2; b1 = b2; c1 = c2; d1 = d2;
for(i = 2; i <=300; i++)
{
d2 = b1 + c1 + 2*d1;
c2 = a1 + 2*c1 + d1;
b2 = a1 + 2*b1 + d1;
a2 = 2*a1 + b1 + c1;
num[i] = a2%100;
/*if(isEqual(a1, a2, i-1))
{
break;
}*/
a1 = a2%100;
b1 = b2%100;
c1 = c2%100;
d1 = d2%100;
}
while(cin >> T && T)
{
for(int j = 1; j <= T; j++)
{
cin >> N;
if(N >=23)
cout << "Case " << j << ": " << num[N%23 + 3] << endl;
else
cout << "Case " << j << ": " << num[N] << endl;
}
cout << endl;
}
return 0;
}
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
int num[26] = {0, 2};
bool isEqual(int a, int b, int l)
{
for(int i = 1; i <= l; i++)
{
if(a == num[i-1] && b == num[i])
return true;
}
return false;
}
int main()
{
ifstream cin("2065.txt");
int T;
__int64 N;
int a1 , a2 = 2, b1 , b2 = 1, c1 , c2 = 1, d1 , d2 = 0, i;
a1 = a2; b1 = b2; c1 = c2; d1 = d2;
for(i = 2; i <=300; i++)
{
d2 = b1 + c1 + 2*d1;
c2 = a1 + 2*c1 + d1;
b2 = a1 + 2*b1 + d1;
a2 = 2*a1 + b1 + c1;
num[i] = a2%100;
/*if(isEqual(a1, a2, i-1))
{
break;
}*/
a1 = a2%100;
b1 = b2%100;
c1 = c2%100;
d1 = d2%100;
}
while(cin >> T && T)
{
for(int j = 1; j <= T; j++)
{
cin >> N;
if(N >=23)
cout << "Case " << j << ": " << num[N%23 + 3] << endl;
else
cout << "Case " << j << ": " << num[N] << endl;
}
cout << endl;
}
return 0;
}
通过观察这个数组,发现一个循环,那么,可以优化程序如下:
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
ifstream cin("2065.txt");
int T;
__int64 N;
int num[26] = {0, 2, 6, 20, 72, 72, 56, 60, 12, 92, 56, 0, 52, 12, 56, 40, 92, 32, 56, 80, 32, 52, 56, 20, 72, 72};
while(cin >> T ,T)
{
for(int j = 1; j <= T; j++)
{
cin >> N;
if(N < 23)
cout << "Case " << j << ": " << num[N] << endl;
else
cout << "Case " << j << ": " << num[(N-3)%20+3] << endl;
}
cout << endl;
}
return 0;
}
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
ifstream cin("2065.txt");
int T;
__int64 N;
int num[26] = {0, 2, 6, 20, 72, 72, 56, 60, 12, 92, 56, 0, 52, 12, 56, 40, 92, 32, 56, 80, 32, 52, 56, 20, 72, 72};
while(cin >> T ,T)
{
for(int j = 1; j <= T; j++)
{
cin >> N;
if(N < 23)
cout << "Case " << j << ": " << num[N] << endl;
else
cout << "Case " << j << ": " << num[(N-3)%20+3] << endl;
}
cout << endl;
}
return 0;
}
很类似网上的代码,其实,网上的代码都是优化后的结果,这也是在AC中要注意的问题。(尽量使用优化后的结果)。

浙公网安备 33010602011771号