zoukankan      html  css  js  c++  java
  • 【YbtOJ#20070】诗人小 K

    题目

    题目链接:http://noip.ybtoj.com.cn/contest/102/problem/4

    思路

    (f[s][i]) 表示 (i-(x+y+z)+1sim i) 的所有后缀中,能构成合法的和的集合。
    定义一个和是合法的,当且仅当等于一段后缀且能没有“跨过” (x)(y)(也就是这个后缀存在一段前缀和为 (x)(y))。
    那么先预处理出 (g[s][i]) 表示状态 (s) 在加入 (i) 这个数之后,可以得到的状态。
    (f[s][i]) 表示到了第 (i) 为,状态为 (s) 的方案数。那么 (f[s][i]) 可以转移到 (f[g[s][k]][i+1])
    然后最终 (sum^{maxn-1}_{i=2^z}f[i][n]) 就是答案。
    时间复杂度 (O(2^zmn+2^zmz))

    代码

    #include <bits/stdc++.h>
    #define reg register
    using namespace std;
    
    const int N=45,MAXN=(1<<17)+10,MOD=1e9+7;
    int n,x,y,z,ans,Maxn,f[MAXN][N],g[MAXN][N];
    
    int main()
    {
    	freopen("poem.in","r",stdin);
    	freopen("poem.out","w",stdout);
    	scanf("%d%d%d%d",&n,&x,&y,&z);
    	y+=x; z+=y; Maxn=(1<<z);
    	for (reg int s=0;s<Maxn;s++)
    		for (reg int i=1;i<=10;i++)
    		{
    			for (reg int j=0;j<z;j++)
    				if (s&(1<<j))
    				{
    					if (i+j+1<=x) g[s][i]|=1<<(i+j);
    					if (i+j+1<=y && j+1>=x) g[s][i]|=1<<(i+j);
    					if (i+j+1<=z && j+1>=y) g[s][i]|=1<<(i+j);
    				}
    			if (i<=x) g[s][i]|=(1<<i-1);
    			if (s&(1<<z-1)) g[s][i]=Maxn-1;
    		}
    	f[0][0]=1;
    	for (reg int i=0;i<n;i++)
    		for (reg int s=0;s<Maxn;s++)
    		{
    			if (!f[s][i]) continue;
    			for (reg int j=1;j<=10;j++)
    				f[g[s][j]][i+1]=(f[g[s][j]][i+1]+f[s][i])%MOD;
    		}
    	for (int s=(1<<z-1);s<Maxn;s++)
    		ans=(ans+f[s][n])%MOD;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    图片上传
    解决Vuex持久化插件-在F5刷新页面后数据不见的问题
    vue登录
    拖动排序的vue组件
    vue图片懒加载
    vue中使用图片预加载
    前端架构知识体系
    html判断IE版本
    HighCharts 在IE8下饼图不显示的问题
    新一代调试王者Console
  • 原文地址:https://www.cnblogs.com/stoorz/p/13842845.html
Copyright © 2011-2022 走看看