1966. 棋盘(chess)

1966. 棋盘(chess)

题目描述
给定一个NM的棋盘,每个格子里最多只可以放置一个棋子,求有多少种放置方案使得任意22的正方形区域内恰有2个棋子。

输入
棋盘的长与宽 N M

输出
一个整数,代表可行的方案数。

样例输入

2 2

样例输出

6

数据范围限制
对于30%的数据 N,M<=20
对于100%的数据 N,M<=10000

思路:
我们先固定头两行和头两列。对于固定的2列,显然有2^m种排列方法,而除了红色的两种第二行会有各两种组合,绿色部分的组合都是唯一固定的,跟n的大小没有关系了。
而对于红色的两种基于n行,都会产生2^(n-1)种组合,共2*2 ^(n-1),也就是2 ^ n。所以我们可以推出最终的方案数:2 ^ n+2 ^ m-2。

在这里插入图片描述
最后,因为本题的数据有点大,所以必须要用高精度来做。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
long long n,m;
int a[10010],b[10010],c[10010],len,len1,maxn,lenc;
void gjc(int mc)
{
	memset(a,0,sizeof(a));
	a[1]=1;len=1;
	for(int i=1;i<=mc;i++)
	{
		int jw=0;
		for(int j=1;j<=len;j++)
		{
            a[j]=a[j]*2+jw;
           	jw=a[j]/10;
			a[j]%=10;
		    if(jw!=0&&j==len) len++;
		}
	}
}
void add()
{
	int x=0;
	while(lenc<=len||lenc<=len1)
	{
		c[lenc]=a[lenc]+b[lenc]+x;
		x=c[lenc]/10;
		c[lenc]%=10;
		lenc++;
	}
	c[lenc]=x;
	memset(a,0,sizeof(a));
	a[1]=2;
	for(int i=1;i<=lenc;i++)
	{
		if(c[i]<a[i]) c[i]+=10,c[i+1]--;
		c[i]-=a[i];
	}
	int i=lenc;
	while(!c[i]&&i>1) i--;
	for(int j=i;j>=1;j--) cout<<c[j];
}
int main()
{
	//fre(chess);
	scanf("%lld%lld",&n,&m);
	gjc(m);
	len1=len;
	memcpy(b,a,sizeof(a));
	gjc(n);
	add();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/106446906