• CCPC2020绵阳 B题 Building Blocks


    Pro:
    https://pintia.cn/problem-sets/1322796904464203776/problems/1322798545527595009
    有一个用小方块搭成的立体图形
    给出它的左前视图每一列的高度
    然后钦定(k)个位置的方块数
    求一共有多少种合法的方案
    (n,m,k<=1e5)

    Sol:
    显然要考虑一个顺着左前序列的一列一列的DP
    每一个高度限制会限制相邻的两列
    也就是说每一列的方块会被两个限制限制
    因此可以考虑(dp[i][0/1])
    表示当前已经放完了(x+y<=i)的所有方块
    (x+y)个限制0/1(是否被满足)的方案数
    按照定义转移即可

    #include<bits/stdc++.h>
    #define N 220000
    #define db double
    #define ll long long
    #define ldb long double
    #define ull unsigned long long
    using namespace std;
    const int h=3,ki=149,mo=1e9+7;
    inline int inc(int x,int k){x+=k;return x<mo?x:x-mo;}
    inline int dec(int x,int k){x-=k;return x>=0?x:x+mo;}
    inline int read()
    {
    	char ch=0;int x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x*flag;
    }
    inline void write(int x)
    {
    	if(!x)return (void)putchar(48);
    	if(x<0)putchar(45),x=-x;
    	int len=0,p[20];
    	while(x)p[++len]=x%10,x/=10;
    	for(int i=len;i>=1;i--)putchar(p[i]+48);
    }
    const db eps=1e-7,inf=1e9+7,pi=acos(-1);
    inline db Read(){db x;scanf("%lf",&x);return x;}
    inline void Write(db x){printf("%lf",x);}
    int ksm(int x,int k)
    {
    	int ans=1;
    	while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}
    	return ans;
    }
    int f(int n,int k){return dec(ksm(n,k),ksm(n-1,k));}
    int g(int n,int k){return ksm(n,k);}
    int p[N],cnt[N],lim[N],dp[N][2];
    void work(int o)
    {
    	int n=read(),m=read(),len=n+m,k=read();
    	for(int i=0;i<=len+1;i++)lim[i]=p[i]=cnt[i]=dp[i][0]=dp[i][1]=0;
    	for(int i=1;i<=len;i++)lim[i]=read();
    	for(int i=1;i<=len-1;i++)cnt[i+1]=min(min(n,m),min(i,len-i));
    	for(int i=1;i<=k;i++)
    	{
    		int x=read(),y=read(),t=read();cnt[x+y]--;
    		p[x+y]=max(p[x+y],t);p[x+y-1]=max(p[x+y-1],t);
    	}
    	for(int i=2;i<=len;i++)if(cnt[i]<0){printf("Case #%d: %d
    ",o,0);return;}
    	for(int i=1;i<=len;i++)if(p[i]>lim[i]){printf("Case #%d: %d
    ",o,0);return;}
    	
    	if(p[1]<lim[1])dp[1][0]=1;else dp[1][1]=1;
    	for(int i=2;i<=len;i++)
    	{
    		int a=lim[i-1],b=lim[i];
    		if(p[i]<lim[i])
    		{
    			if(a==b)dp[i][1]=inc(dp[i][1],1ll*dp[i-1][0]*f(a,cnt[i])%mo);
    			if(a>=b)dp[i][1]=inc(dp[i][1],1ll*dp[i-1][1]*f(b,cnt[i])%mo);
    			if(a<b)dp[i][0]=inc(dp[i][0],1ll*dp[i-1][0]*f(a,cnt[i])%mo);
    			dp[i][0]=inc(dp[i][0],1ll*dp[i-1][1]*g(min(a,b-1),cnt[i])%mo);
    		}
    		else
    		{
    			if(a<=lim[i])dp[i][1]=inc(dp[i][1],1ll*dp[i-1][0]*f(a,cnt[i])%mo);
    			dp[i][1]=inc(dp[i][1],1ll*dp[i-1][1]*g(min(a,b),cnt[i])%mo);
    			dp[i][0]=0;
    		}
    	}
    	printf("Case #%d: %d
    ",o,dp[len][1]);
    }
    int main()
    {
    	int t=read();
    	for(int i=1;i<=t;i++)work(i);
    	return 0;
    }
    
  • 相关阅读:
    今年暑假不AC
    Java类的生命周期
    Java反射机制
    Java环境变量的配置及使用
    javaIO流(一)
    ftp服务器测试
    linux下svn使用及查看杀掉进程
    网络配置学习
    网络配置指令
    dos攻击与防御
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/13931125.html
Copyright © 2020-2023  润新知