zoukankan      html  css  js  c++  java
  • 1594:涂抹果酱

    1594:涂抹果酱
    时间限制: 1000 ms 内存限制: 524288 KB
    提交数: 669 通过数: 269
    【题目描述】
    Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕。蛋糕俯视图是一个 N×M 的矩形,它被划分成 N×M 个边长为 1×1 的小正方形区域(可以把蛋糕当成 N 行 M 列的矩阵)。蛋糕很快做好了,但光秃秃的蛋糕肯定不好看!所以,Sam 要在蛋糕的上表面涂抹果酱。果酱有三种,分别是红果酱、绿果酱、蓝果酱,三种果酱的编号分别为 1,2,3。为了保证蛋糕的视觉效果,Admin 下达了死命令:相邻的区域严禁使用同种果酱。但 Sam 在接到这条命令之前,已经涂好了蛋糕第 KK 行的果酱,且无法修改。
    现在 Sam 想知道:能令 Admin 满意的涂果酱方案有多少种。请输出方案数 mod106 。若不存在满足条件的方案,请输出 0。
    【输入】
    输入共三行。
    第一行:N,M;
    第二行:K;
    第三行:M 个整数,表示第 K 行的方案。
    字母的详细含义见题目描述,其他参见样例。
    【输出】
    输出仅一行,为可行的方案总数。
    【输入样例】
    2 2
    1
    2 3
    【输出样例】
    3
    【提示】
    样例说明:
    方案一
    23
    12
    数据范围与提示:
    对于 30% 的数据,1≤N×M≤20;
    对于 60% 的数据,1≤N≤1000,1≤M≤3;
    对于 100% 的数据,1≤N≤10000,1≤M≤5。

    思路:
    其实也是一道板子题,不同的是相较于前两道题来说,这道题的状态应该使用三进制来存储(因为有三种果酱)。三进制的转移只需要开一个数组模拟三进制运算过程,其它的和二进制就基本上差不多啦(不要看下面我写的代码,又臭又长,还超时,[我也不知道是什么问题],其实最终代码非常短,只需要大概60行左右?)

    代码:

    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    inline ll read()//快读 
    {
        char c=getchar();
        ll x=0,f=1;
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}//不需要判负删掉来简化 
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        return x*f;
    }
    void write(int a)//快写 
    {
        if(a<0) putchar('-'),a=-a;//不需要判负删掉来简化
        if(a>=10)write(a/10);
        putchar(a%10+48);
    }
    
    ll c[10200],f[10200][200],n,m;
    ll a[10200];
    ll k;ll num=0;
    const int mod=1e6;
    
    inline bool check(int x)
    {
    	for(int i=m-1;i;i--)
    	{
    		if(x%c[i+1]/c[i]==x%c[i]/c[i-1]) return 0;
    	}
    	return 1;
    }
    
    inline bool check2(int x,int y)
    {
    	for(int i=m-1;i>=0;i--)
    	{
    		if((x%c[i+1]/c[i])==(y%c[i+1]/c[i])) return 0;
    	}
    	return 1;
    }
    ll cnt=0;
    inline void prepare()
    {
    	
    	for(int i=0;i<c[m];i++)
    	{
    		if(check(i)) a[++cnt]=i;
    		if(i==num) f[0][cnt]=1;//表示将第k行当做第0行去处理 
    	}
    }//所有状态都被预处理完成 
    
    inline void dp()
    {
    	
    	ll x=max(n-k,k-1);
    	
    	ll y=min(n-k,k-1);
    	
    	for(int i=1;i<=x;i++)
    		for(int j=1;j<=cnt;j++)
    		{
    			for(int l=1;l<=cnt;l++)
    			{
    				if(check2(a[l],a[j]))
    				{
    					f[i][j]=(f[i-1][l]+f[i][j])%mod;
    				}
    			}
    		}
    		
    	ll ans1=0,ans2=0;
    	for(int i=1;i<=cnt;i++)
    	{
    		ans1+=f[x][i];
    		ans1%=mod;
    		ans2+=f[y][i];
    		ans2%=mod; 
    	}
    	
    	write(ans1*ans2%mod);
     } 
    
    int main()
    {
    	n=read();
    	m=read();
    	k=read();
    	
    	c[0]=1;
    	
    	for(int i=1;i<=m;i++)
    	{
    		int s;
    		s=read();
    		num=num*3+s-1;//将第k行的状态转化成三进制
    		c[i]=c[i-1]*3; 
    	}
    	
    	if(check(num)==0) 
    	{
    		write(0);
    		return 0;
    	}
    	
    	prepare();
    	
    	dp();
    	 
    	return 0;
    }
    
    
    /*
    算法流程:
    1.判断k行是否有冲突
    2.k行无冲突,预处理各行的状态
    3.状态处理完成后进行dp,注意只需要dp一般,
    方案数都是一样的 
    */
    
  • 相关阅读:
    [Leetcode] generate parentheses 生成括号
    [Leetcode] letter combinations of a phone number 电话号码的字母组合
    MySQL安装出现“不是内部或外部命令,也不是可执行程序”等一系列问题的解决方案
    [Leetcode] sudoku solver 求解数独
    [Leetcode] valid sudoku 有效数独
    jQuery使用(七):事件绑定与取消,及自定事件的实现原理
    前端交互体验核心之事件(一)
    jQuery使用(六):DOM操作之元素包裹、克隆DOM与data的综合应用
    jQuery使用(五):DOM操作之插入和删除元素
    jQuery使用(四):DOM操作之查找兄弟元素和父级元素
  • 原文地址:https://www.cnblogs.com/yxr001002/p/14427346.html
Copyright © 2011-2022 走看看