hdu2065--红色病毒
来源:互联网 发布:工商银行网络银行 编辑:程序博客网 时间:2024/04/30 12:13
现在有一长度为N的字符串,满足一下条件:
(1) 字符串仅由A,B,C,D四个字母组成;
(2) A出现偶数次(也可以不出现);
(3) C出现偶数次(也可以不出现);
计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据肯能非常庞大,你只要给出最后两位数字即可.
Input
Output
Sample Input
41420113142460
Sample Output
Case 1: 2Case 2: 72Case 3: 32Case 4: 0Case 1: 56Case 2: 72Case 3: 56 看了下网上的题解,大致是下面两种解法。1.泰勒推导转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题源:http://acm.hdu.edu.cn/showproblem.php?pid=2065
比赛的时候遇到这种题,只能怪自己高数学得不好,看着别人秒。。。。
由4种字母组成,A和C只能出现偶数次。
构造指数级生成函数:(1+x/1!+x^2/2!+x^3/3!……)^2*(1+x^2/2!+x^4/4!+x^6/6!……)^2.
前面是B和D的情况,可以任意取,但是相同字母一样,所以要除去排列数。后者是A和C的情况,只能取偶数个情况。
根据泰勒展开,e^x在x0=0点的n阶泰勒多项式为 1+x/1!+x^2/2!+x^3/3!……
而后者也可以进行调整,需要把奇数项去掉,则e^(-x)的展开式为1-x/1!+X^2/2!-X^3/3!……
所以后者可以化简为(e^x+e^(-x))/2。则原式为(e^x)^2 * ((e^x*e^(-x))/2)^2
整理得到e^4x+2*e^2x+1。
又由上面的泰勒展开
e^4x = 1 + (4x)/1! + (4x)^2/2! + (4x)^3/3! + ... + (4x)^n/n!;
e^2x = 1 + (2x)/1! + (2x)^2/2! + (2x)^3/3! + ... + (2x)^n/n!;
对于系数为n的系数为(4^n+2*2^n)/4=4^(n-1)+2^(n-1);
快速幂搞之。
2.递推关系转载出处 http://blog.csdn.net/welcome_z/article/details/7892353
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #include<vector>
- #include<cmath>
- #define LL long long
- #define MOD 100
- #define eps 1e-6
- #define N 100010
- #define zero(a) fabs(a)<eps
- using namespace std;
- int PowMod(int a,LL b){
- int ret=1;
- while(b){
- if(b&1)
- ret=(ret*a)%MOD;
- a=(a*a)%MOD;
- b>>=1;
- }
- return ret;
- }
- int main(){
- int t;
- while(scanf("%d",&t)!=EOF&&t){
- int cas=0;
- LL n;
- while(t--){
- scanf("%I64d",&n);
- printf("Case %d: %d\n",++cas,(PowMod(4,n-1)+PowMod(2,n-1))%MOD);
- }
- printf("\n");
- }
- return 0;
- }
问题分析Problem Analyse 递推题
Algorithm Analyse 比起以前做过的递推题,这一题算比较麻烦的了(当然,原因是我没有想到
好的方法,如果你有更方便的方法,欢迎提供大家一起学习)。如果没有任何条件限制,A、B、C、D组成长度为n的字符串,其个数应该为:4n。
因为有了A、C需要出现偶数次的要求,就出现合法和不合法的不同分组。在不合法的组里,又有1.A出现奇数次、C出现偶数次;2.C出现奇数次、A出现偶数次;3.A出现奇数次、C出现奇数次;三种情况。
我们用数组f[n][0]保存长度为n,合法的字符串的个数。f[n][1]保存长度为n,仅A出现奇数次的字符串的个数。f[n][2]保存长度为n,仅C出现奇数次的字符串的个数。f[n][3]保存长度为n,A、C出现奇数次的字符串的个数。
f[n][0]长度为n-1的合法字符串在末尾加上一个B或者D,都可以变成长度为n的合法字符串。长度为n-1的仅A出现奇数次的字符串再在末尾加上一个A,也可以变成合法字符串。长度为n-1的仅C出现奇数次的字符串再在末尾加上一个C,也可以变成合法字符串。所以,f[n][0] = 2 × f[n-1][0] + f[n-1][1] + f[n-1][2];
f[n][1]长度为n-1的合法字符串在末尾加上A,都可以变成长度为n的仅A出现奇数次的字符串。长度为n-1的仅A出现奇数次的字符串再在末尾加上一个B或者D,也可以变成仅A出现奇数次的字
符串。长度为n-1的A、C出现奇数次的字符串再在末尾加上一个C,也可以变成仅A出现奇数次的字符串
。所以,f[n][1] = 2 × f[n-1][1] + f[n-1][0] + f[n-1][3];
f[n][2]长度为n-1的合法字符串在末尾加上C,都可以变成长度为n的仅C出现奇数次的字符串。长度为n-1的仅C出现奇数次的字符串再在末尾加上一个B或者D,也可以变成仅C出现奇数次的字
符串。长度为n-1的A、C出现奇数次的字符串再在末尾加上一个A,也可以变成仅C出现奇数次的字符串
。所以,f[n][2] = 2 × f[n-1][2] + f[n-1][0] + f[n-1][3];
f[n][3]长度为n-1的A、C出现奇数次的字符串在末尾加上一B或者D,都可以变成长度为n的A、C出现奇数
次的字符串。长度为n-1的仅A出现奇数次的字符串再在末尾加上一个C,也可以变成A、C出现奇数次的字符串
。长度为n-1的仅C出现奇数次的字符串再在末尾加上一个A,也可以变成A、C出现奇数次的字符串
。所以,f[n][3] = 2 × f[n-1][3] + f[n-1][1] + f[n-1][2];
综上所述,我们得到:f[n][0] = 2 × f[n-1][0] + f[n-1][1] + f[n-1][2]; ①f[n][1] = 2 × f[n-1][1] + f[n-1][0] + f[n-1][3]; ②f[n][2] = 2 × f[n-1][2] + f[n-1][0] + f[n-1][3]; ③f[n][3] = 2 × f[n-1][3] + f[n-1][1] + f[n-1][2]; ④
f[1][0] = 2f[1][1] = 1f[1][2] = 1f[1][3] = 0
/**** 搞出这个我就很哈皮的去敲快速幂了。。。然而大牛。。。 ****/
发现f[1][1]与f[1][2]初始状态相同,而且以后迭代方程也相同,所以f[n][1] = f[n][2]又有f[n][0] + f[n][3] = f[n][1] + f[n][2]∵f[n][0] + f[n][1] + f[n][2] + f[n][3] = 4^n∴f[n][0] + f[n][3] = f[n][1] + f[n][2] = 2 × 4^(n-1)∴f[n-1][1] + f[n-1][2] = 2 × 4^(n-2)∴f[n][0] = 2 × f[n-1][0] + f[n-1][1] + f[n-1][2] = 2 × f[n-1][0] + 2 × 4^(n-2)
我们得到:f[n][0] = 2 × f[n-1][0] + 2^(2n-3)f[n-1][0] = 2 × f[n-2][0] + 2^(2n-5)┋f[n-m][0] = 2 × f[n-m-1][0] + 2^(2n-2m-3)┋f[2][0] = 2 × f[1][0] + 2^1f[1][0] = 2
开始一层层往下迭代:f[n][0]= 2 × f[n-1][0] + 2^(2n-3)= 2^2 × f[n-2][0] + 2^(2n-4) + 2^(2n-3)┋= 2^m × f[n-m][0] + 2^(2(n-m)-1+m-1) + … + 2^(2n-3)= 2^(n-1) × f[1][0] + 2^(n-1) + 2^n +… + 2^(2n-3)f[1][0] = 2;
∴f[n][0] = 2^n + 2^(n-1) + 2^n +… + 2^(2n-3) = 2^(2n-2) + 2^(n-1)
算法实现
Programing 公式得到了:f(n) = 2^(2n-2) + 2^(n-1)但就这样直接编程那是不可能实现的,因为n的范围1≤N<=2^64怎么的范围,是不能求出f(n)的。所以还得找其他规律。因为题目只要求输出最后2位数,我们依次输出2的n的最后两位看看…2^0 12^1 22^2 42^3 82^4 162^5 322^6 642^7 282^8 562^9 122^10 242^11 482^12 962^13 922^14 842^15 682^16 362^17 722^18 442^19 882^20 762^21 522^22 4到了2^22时,末尾2位又变成4,与2^2一样,这时候就进入了一个循环了(每20个一次循环)。所以,结果只能是这22个中的一个。只有n=0 和 n=1是需要特殊考虑的。其他n就等于2(n-2) %20 + 2的值了。
两种方法都很好,特地整理收藏起来。
- #include <iostream>
- using namespace std;
- int p2[30] = {1};
- int po(__int64 x)
- {
- if (x>1) x = (x - 2)% 20 + 2;
- if (x<0) return 1;
- return p2[x];
- }
- int main()
- {
- for (int i=1;i<24;++i) p2[i] = (p2[i-1]<<1) % 100;
- int t;
- while (scanf("%d", &t), t)
- {
- for (int i=1;i<=t;++i)
- {
- __int64 n, a;
- scanf("%I64d", &n);
- a = po(2*n-2) + po(n-1);
- printf("Case %d: %d\n", i, a%100);
- }
- printf("\n");
- }
- return 0;
- }
- hdu2065--红色病毒
- hdu2065"红色病毒"问题
- HDU2065 "红色病毒"问题 【数论】
- HDU2065 "红色病毒"问题 【快速幂】
- 【快速幂】HDU2065"红色病毒"问题
- 【HDU2065】"红色病毒"问题 母函数
- hdu2065 “红色病毒” 指数型母函数
- HDU2065 “红色病毒”——运用母函数求解
- 【指数型母函数+非递归快速幂】【HDU2065】"红色病毒"问题
- HDU2065
- hdu2065
- hdu2065
- 红色代码病毒分析
- 红色代码病毒分析
- "红色病毒"问题
- HD 2056 红色病毒
- hdu 2065 红色病毒
- HDOJ2065 “红色病毒”问题
- copy_to_user和copy_from_user两个函数的分析
- Utilities之auto_ptr
- 【转】DataGridView 的重绘
- DOM解析XML(二)
- try catch多个catch捕获问题
- hdu2065--红色病毒
- Unlities之numeric_limits
- c++ double类型的误差
- [iOS Crash文件分析]-如何使用symbolicatecrash工具
- 烤鸭的gerrit使用总结
- 单元测试之覆盖率浅谈
- 怎么查询局域网内全部电脑IP和mac地址等信息?
- 人脸识别之LBPH
- CCS3.1调试总结