标签:
给你一个
左下角是
首先根据对称性,我们可以有:if(W<H) swap(W,H);
然后由于隔空也可以攻击,我们可以有:
if(W>N) W=N;
if(H>N) H=N;
这样我们就可以做到少一点情况了。
然后我们会发现只有这么几种情况:
1.
2.(图片来自这里)
这种情况下我们就可以先确定右边突出来的部分怎么放,然后在确定左边的
3.
重点是这种情况,我们可以将其分成7块,就根据这两个棋盘的边界可以把其分成7个块,然后我们dp就行了。但是由于本人水平底下,然后又要写高精度,然后我的程序就光荣的
具体如何排列组合请看代码。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define C(a,b) (fac[(a)]/fac[(b)]/fac[(a)-(b)])
#define P(a,b) (fac[(a)]/fac[(a)-(b)])
const int Mod=10;
using namespace std;
int N,M,W,H,K;
struct gjd_
{
long long cnmbdctr[600];
};
long long fac[30];
struct gjd_ ans={0};
int G[10]={0};
struct gjd_ operator * (struct gjd_ a1,long long a2)
{
if(a2%10==0 && a2!=10)
return a1*(a2/10)*10;
struct gjd_ bb=a1;
for(int i=1;i<=bb.cnmbdctr[0];i++)
{
bb.cnmbdctr[i]*=a2;
if(bb.cnmbdctr[i-1]>=Mod && i!=1)
{
bb.cnmbdctr[i]+=bb.cnmbdctr[i-1]/Mod;
bb.cnmbdctr[i-1]%=Mod;
}
}
for(int i=bb.cnmbdctr[0];bb.cnmbdctr[i]>=Mod;bb.cnmbdctr[0]++,i++)
bb.cnmbdctr[i+1]+=bb.cnmbdctr[i]/Mod,bb.cnmbdctr[i]%=Mod;
return bb;
}
struct gjd_ operator + (struct gjd_ a1,struct gjd_ a2)
{
struct gjd_ bb={0};
bb.cnmbdctr[0]=max(a1.cnmbdctr[0],a2.cnmbdctr[0]);
for(int i=1;i<=bb.cnmbdctr[0];i++)
{
bb.cnmbdctr[i]+=a1.cnmbdctr[i]+a2.cnmbdctr[i];
if(bb.cnmbdctr[i]>=Mod)
{
bb.cnmbdctr[i+1]+=bb.cnmbdctr[i]/Mod;
bb.cnmbdctr[i]%=Mod;
if(i==bb.cnmbdctr[0])
bb.cnmbdctr[0]++;
}
}
return bb;
}
void prt(struct gjd_ a1)
{
printf("%d",(int)a1.cnmbdctr[a1.cnmbdctr[0]]);
for(int i=a1.cnmbdctr[0]-1;i>=1;i--)
printf("%d",(int)a1.cnmbdctr[i]);
return;
}
void counts()
{
struct gjd_ add={1,1};
add=add*C(W,G[1]);
add=add*P(H,G[1])*C(W-G[1],G[2])*P(N-H,G[2]);
add=add*C(H-G[1],G[3])*P(N-W,G[3])*C(N-W-G[3],G[4])*P(N-H-G[2],G[4]);
add=add*C(N-W-G[3]-G[4],G[5])*P(M-(N-H),G[5])*C(N-H-G[2]-G[4],G[6])*P(M-(N-W),G[6]);
add=add*C(M-(N-H)-G[5],G[7])*P(M-(N-W)-G[6],G[7]);
ans=ans+add;
return;
}
void dfs(int cnt,int re)
{
int Max;
if(cnt==7)
{
Max=min(M-(N-H)-G[5],M-(N-W)-G[6]);
if(re<=Max)
{
G[7]=re;
counts();
}
return;
}
else if(cnt==1)
Max=min(min(W,H),re);
else if(cnt==2)
Max=min(min(W-G[1],N-H),re);
else if(cnt==3)
Max=min(min(H-G[1],N-W),re);
else if(cnt==4)
Max=min(min(N-W-G[3],N-H-G[2]),re);
else if(cnt==5)
Max=min(min(N-W-G[3]-G[4],M-(N-H)),re);
else if(cnt==6)
Max=min(min(N-H-G[2]-G[4],M-(N-W)),re);
for(int i=0;i<=Max;i++)
{
G[cnt]=i;
dfs(cnt+1,re-i);
}
return;
}
int main()
{
scanf("%d%d%d%d%d",&N,&M,&W,&H,&K);
fac[0]=1;
for(int i=1;i<=20;i++) fac[i]=fac[i-1]*i;
if(W<H) swap(W,H);
if(W>N) W=N;
if(H>N) H=N;
if(N>=M+W)
{
if(K<=N)
{
ans.cnmbdctr[0]=ans.cnmbdctr[1]=1;
ans=ans*C(N,K);
ans=ans*P(N,K);
}
prt(ans);
}
else if(N>=M+H)
{
if(K>N) cout<<0<<endl;
else
{
int MM=M+W-N;
for(int i=0;i<=min(MM,K);i++)
{
struct gjd_ gg={1,1};
gg=gg*C(M,i);gg=gg*P(MM,i);gg=gg*C(N-i,K-i);gg=gg*P(N,K-i);
ans=ans+gg;
}
prt(ans);
}
}
else
{
dfs(1,K);
prt(ans);
}
return 0;
}
sgu-241 The United Fields of Chessboardia
标签:
原文地址:http://blog.csdn.net/qq_21995319/article/details/45697439