真的猛士,敢于开数学!!!!!
Posted guaguastandup
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了真的猛士,敢于开数学!!!!!相关的知识,希望对你有一定的参考价值。
dp专题看得差不多了,本来是想看图论,
但是那天物理课,莫名打开了数学专题
看了一半也不太好,就先看完再说吧~
数学专题不用markdown好难写啊
1.组合数学
UVa580
题意:一个长度为n的序列(n<=30),由若干U,L组成
有大于等于3个连续的U的序列则为危险序列
求危险序列的数量
方法一:(LRJ)
f(n)=(1<<n-3) + sigma ( g(i-2)*(1<<(n-i-2) ) (i from 2 to n-2) g(i)=(1<<i)-f(i)
g表示长度为i的安全序列的个数
因为题目的要求是最少三个U,那么则假设第i,i+1,i+2,位置放置的U使序列“由安全变成危险”
也就是说,希望第i个位置的U起决定性作用
那么为了防止前面已经有序列起到决定性作用,我们使第i-1个一定为L
---->对于第i个位置,有g(i-2)*(1<<(n-i-2))
---->前i-2个没有危险序列的个数 * 第(i+3~n)个任意排列
式子里面的 (1<<n-3)指的是i==1的情况
因为求和是从i==2开始的
f[0]=f[1]=0=f[2]=0; g[0]=1,g[1]=2,g[2]=4;
1 #include<bits/stdc++.h> 2 using namespace std; 3 int f[40], g[40]; 4 int main(){ 5 f[0] = f[1] = f[2] = 0; 6 g[0] = 1, g[1] = 2, g[2] = 4; 7 for (int i = 3; i <= 35;i++){ 8 f[i] = (1 << (i - 3)); 9 for (int j = 2; j <= i-2;j++){ 10 f[i] += g[j - 2] * (1 << (i - j - 2)); 11 } 12 g[i] = (1 << i) - f[i]; 13 } 14 int n; 15 while(cin>>n&&n){ 16 cout << f[n] << endl; 17 } 18 system("pause"); 19 return 0; 20 }
方法二:
dp[i]表示第i位为L结尾的序列数量:
dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
对于第i-1个位置 我们想要放置U,但是序列不危险,则可以考虑,让i-1,i-2,i-3的任何一个不为U(加法计数)
dp[1]=1,dp[2]=2,dp[3]=4,dp[4]=7;
1 #include<bits/stdc++.h> 2 using namespace std; 3 int f[40]; 4 int main(){ 5 f[1] = 1, f[2] = 2, f[3] = 4; 6 for (int i = 4; i <= 32;i++){ 7 f[i] = f[i - 1] + f[i - 2] + f[i - 3]; 8 } 9 int n; 10 while(cin>>n&&n){ 11 int ans = (1 << n); 12 ans -= f[n + 1]; 13 cout << ans << endl; 14 } 15 }
个人觉得第一种的思路比较好想(容易想错),第二种的更简洁
好无聊,不想写了
以上是关于真的猛士,敢于开数学!!!!!的主要内容,如果未能解决你的问题,请参考以下文章