当前位置: 首页 > 工具软件 > Critical Mass > 使用案例 >

Critical Mass UVA - 580

彭阳朔
2023-12-01

问题

分析

//dp
#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int maxn=35;
//dp[i][0]是i个,结尾是L,dp[i][1]代表结尾是1个U,dp[i][2]代表结尾两个U,j>=3代表非法,不计算  dp代表答案有多少种
//dp计算不含有U长度>=3的情况数量,没有连续3个的U,那么U最多两个相连,所以按照结尾连续的U的数量进行分类
int dp[maxn][3],n,ans[maxn];

int main(void){
    dp[1][0]=1;
    dp[1][1]=1;
    for(int i=2;i<=30;++i){
        dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2];
        dp[i][1]=dp[i-1][0];
        dp[i][2]=dp[i-1][1];
    }
    //用总情况的数量减去不包括U长度>=3的数量
    for(int i=1;i<=30;++i) ans[i]=(1<<i)-dp[i][0]-dp[i][1]-dp[i][2];
    while(scanf("%d",&n)==1 && n){
        printf("%d\n",ans[n]);
    }
    return 0;
}

设答案为f(n),长度为n,至少有三个连续的U的情况数量,就是一个函数,那么如何求这个函数呢? 设 i , i + 1 , i + 2 , 1 < = i < = n − 2 i,i+1,i+2,1<=i<=n-2 i,i+1,i+21<=i<=n2是最靠左边的连续三个U,所以对于1-i-1这一段,是没有三个连续的U的,所以i-2肯定是L,如果i-2是U,那么i,i+1,i+2就不是最靠左的了。所以1-i-2是没有三个连续的U,那么就是 g ( i − 2 ) = 2 i − 2 − f ( i − 2 ) g(i-2)=2^{i-2}-f(i-2) g(i2)=2i2f(i2)这么多种,右边是 2 n − i − 2 2^{n-i-2} 2ni2种,f(0)=f(1)=f(2)=0,f(3)=1,g(0)=1,当i=1时,没有i-1位存在,i-2=-1,一共有 2 n − 3 2^{n-3} 2n3种,所以 f ( n ) = 2 n − 3 f(n)=2^{n-3} f(n)=2n3,所以长度为n时, 1 < = i < = n − 2 1<=i<=n-2 1<=i<=n2,依次相加得到 f ( n ) = 2 n − 3 + ∑ i = 2 n − 2 g ( i − 2 ) ∗ 2 n − i − 2 f(n)=2^{n-3}+\sum_{i=2}^{n-2}g(i-2)*2^{n-i-2} f(n)=2n3+i=2n2g(i2)2ni2

#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int maxn=35;
int f[maxn],g[maxn],n;

int main(void){
    f[3]=1;
    g[0]=1;
    g[1]=2;
    for(int i=4;i<=30;++i){
        f[i]=2*f[i-1]+g[i-4];  //f[n]=2*f[n-1]+g[n-4]
        g[i-2]=(1<<(i-2))-f[i-2];
    }
    while(scanf("%d",&n)==1 && n){
        printf("%d\n",f[n]);
    }
    return 0;
}
 类似资料:

相关阅读

相关文章

相关问答