zoukankan      html  css  js  c++  java
  • bzoj 4806 炮

    Written with StackEdit.

    Description

    众所周知,双炮叠叠将是中国象棋中很厉害的一招必杀技。炮吃子时必须隔一个棋子跳吃,即俗称"炮打隔子"。

    炮跟炮显然不能在一起打起来,于是(rly)一天借来了许多许多的炮在棋盘上摆了起来……他想知道,在(N×M)的矩形

    方格中摆若干炮(可以不摆)使其互不吃到的情况下方案数有几种。

    棋子都是相同的。

    Input

    一行,两个正整数(N)(M)
    (N<=100,M<=100.)

    Output

    一行,输出方案数(mod) (999983)

    Sample Input

    1 3

    Sample Output

    7

    Solution

    • 易知一行或一列最多只能放两个炮.
    • 注意到炮和皇后不一样,交换两行或两列是不影响的.
    • 所以我们不用记录具体的哪些列上有炮,只需要记录有(1)个炮的有几列,有(2)个炮的有几列就可以了.
    • (f[i][j][k])表示放好前(i)行,其中(j)列有(1)个炮,(k)列有(2)个炮的方案数.
    • 转移的时候,讨论一下放(0/1/2)个炮,炮放在有(0/1)个炮的位置,刷表转移即可.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    int n,m;
    const int P=999983;
    inline int add(int a,int b)
    {
    	return (a + b) % P;
    }
    inline int mul(int a,int b)
    {
    	return 1LL * a * b % P;
    }
    const int MAXN=110;
    int f[MAXN][MAXN][MAXN];
    inline void upd(int &x,int y)
    {
    	x=add(x,y);
    }
    int main()
    {
    	n=read(),m=read();
    	f[0][0][0]=1;
    	for(int i=0; i<=n-1; ++i)
    		for(int j=0; j<=m; ++j)//j列放了1个
    			for(int k=0; j+k<=m; ++k)//k列放了2个
    				{
    					if(!f[i][j][k])
    						continue;
    					int p=m-j-k;//没有炮的列数 
    					//一行最多放2个炮 
    					upd(f[i+1][j][k],f[i][j][k]);//不放
    					if(p>=1)
    						upd(f[i+1][j+1][k],mul(p,f[i][j][k]));//0 -> 1
    					if(j>=1)
    						upd(f[i+1][j-1][k+1],mul(j,f[i][j][k]));//1 -> 2
    					if(p>=1 && j>=1)
    						upd(f[i+1][j][k+1],mul(p*j,f[i][j][k]));//0 1 -> 1 2
    					if(p>=2)
    						upd(f[i+1][j+2][k],mul(p*(p-1)/2,f[i][j][k]));//0 0 -> 1 1
    					if(j>=2)
    						upd(f[i+1][j-2][k+2],mul(j*(j-1)/2,f[i][j][k]));//1 1 -> 2 2
    				}
    	int ans=0;
    	for(int j=0; j<=m; ++j)
    		for(int k=0; j+k<=m; ++k)
    			upd(ans,f[n][j][k]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    角学习教程
    用AngularJS指令扩展HTML
    MVC 6动态导航菜单从数据库
    从Angular5和ASP开始。网络核心
    .NET中的音乐符号
    在Blazor的音乐符号-第二部分
    ASP。NET Core 2.1:集成VMD.RESTApiResponseWrapper。REST API应用程序的核心
    AsyncHttpClient
    Mina
    Volley
  • 原文地址:https://www.cnblogs.com/jklover/p/10095832.html
Copyright © 2011-2022 走看看