RED VIRUS

最近发现一种新病毒,因为其蔓延速度与最近在Internet上传播的“红色 代码 ”不相上下,所以被称作“红色病毒”。经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶、腺嘌呤均是成对出现的。为了搞清楚该病毒的特征,你要对此做出研究。你要得到的是在这个特征下,可能成为病毒的DNA单链序列的个数。更精确的说,你要统计所有满足下列条件的长度为n的字符串的个数:       1.字符串仅右A,T,C,G组成。       2.A出现偶数次,或者不出现。       3.C出现偶数次,或者不出现。       例如,当n=2时,满足条件的字符串有如下6个:       TT,TG,GT,CG,AA,CC。       这个数可能非常大,所以只需输出最后两位数字。           输入:       redvirus.in       输入文件每行给出一个n,1<=n<=10^9,最后以0结束。           输出:       对每个n,输出满足条件的字符串个数的最后两位数字。           输入样例:       1       2       3       100       0           输出样例:       2       6       20       32           限时:       每个n限时5秒。           注意:n的取值很大,不能直接使用递推法。

---------------------------------------------------------------------------------------------------------------------------------------------

下面是解题思路:         令     f(i) 字符串长度为i时,A,C的个数都为偶数的字符串的个数。 (A)     g(i) 字符串长度为i时,A,C的个数都为奇数的字符串的个数。 (B)     h(i) 字符串长度为i时,A,C的个数一个为奇数,另一个为偶数的字符串的个数。 (C)     显然,有:     f(i)+g(i)+h(i)=4^i (1)         根据题意,有     f(1)=2 g(1)=0 h(1)=2         递推:     i)   n=1时,f(1)=1,g(1)=0,h(1)=2     ii)     n=n+1时,有     f(n)=f(n-1)*2+h(n-1)     g(n)=g(n-1)*2+h(n-1)     解释如下:     任意一个长度为n-1的、符合条件(A)的字符串加上一个T或者G即可构成一个长度为n的、符合条件(A)的字符串。所以有f(n-1)*2。     任意一个长度为n-1的、符合条件(B)的字符串加上A,C中个数为奇数的字符集可构成一个长度为n的、符合条件(A)的字符串。所以有h(n-1)。     g(n)的构造方法也一样。     由(1)得     h(n)=4^n-f(n)-g(n)     所以     h(n)=4^n-f(n-1)*2-g(n-1)*2-h(n-1)*2             =4^n-2*(f(n-1)+g(n-1)+h(n-1))             =4^n-2*4^(n-1)             =2*4^(n-1)     代入,得     f(n)=f(n-1)*2+2*4^(n-2)             =2f(n-1)+2^(2n-3)     f(n+1)=2f(n)+2^(2n-1)     为a(n+1)=pa(n)+q(n)形式的递推式,求通项公式,得     f(n)=2^n+2^(2n-2)-2^(n-1)             =2^(n-1)+2^(2n-2)         将2^k的后两位val(k)列表     k 1 2 3 4 5 6 7 8 9 10     val 02 04 08 16 32 64 28 56 12 24     k 11 12 13 14 15 16 17 18 19 20     val 48 96 92 84 68 36 72 44 88 76     k 21 22     val 52 04     因为val(k)=2*val(k-1)   mod   100,又因为val(2)=val(22),所以val的值在val(2)以后以20为周期循环。     所以,有     val(1)=2     val(k)=val((k-2)   mod   20+2) (k>1)         实现:     CONST               pow2 :   array   [   2   ..   21   ]   of   byte   =   (                   4,   8,   16,   32,   64,   28,   56,   12,   24,                   48,   96,   92,   84,   68,   36,   72,   44,                   88,   76,   52   );         Function   pow_two(   n   :   longint   )   :   byte {   计算2^n的后两位   }     Begin               if   n   =   1   then               begin                         pow_two   :=   2;                         exit;               end;               pow_two   :=   pow2[   (   n   -   2   )   mod   20   +   2   ];     End;         然后根据上述公式计算即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值