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;
}