sgu220&sgu221 分类: sgu 2015-06-15 22:01 24人阅读 评论(0) 收藏
首先按横纵坐标之和的奇偶性对棋盘染色,
可以发现染色不同的方格之间是不会互相影响的。
把棋盘旋转
只考虑白色方格上的棋子,原本是沿对角线移动,
但此时它们沿水平方向和竖直方向移动。
注意到菱形方格图中每行的方格数不全相同,
所以按方格数从小到大的先后顺序处理行,以避免后效性。
有
复杂度:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
const int sz = 11;
int n, k, c[2];
long long f[2][sz][sz*sz];
long long ans;
int lcnt[sz<<1];
int linecnt(int t)
{
return (t<=n)?t:((n<<1)-t);
}
void solve(int x)
{
f[x][0][0] = 1;
for(int i = 1; ((i<<1)-x) <= (n<<1); c[x] = i++)
lcnt[i] = linecnt((i<<1)-x);
std::sort(lcnt + 1, lcnt + c[x] + 1);
for(int i = 1; i <= c[x]; i++)
for(int j = 0; j <= k && j <= lcnt[i]; j++)
f[x][i][j] = f[x][i-1][j] + f[x][i-1][j-1]*(lcnt[i]-j+1);
}
void getans()
{
for(int i = 0; i <= k; i++)
ans += f[0][c[0]][i]*f[1][c[1]][k-i];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu220.in","r",stdin);
freopen("sgu220.out","w",stdout);
#endif
std::cin >> n >> k;
solve(0), solve(1), getans();
std::cout << ans;
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
const int sz = 51, Base = 10000;
struct BigNum
{
int num[sz], l;
}emp;
int n, k;
BigNum f[2][sz][sz*sz];
BigNum ans;
int c[2], lcnt[sz<<1];
void digit(int &plus,int &tp)
{
plus += tp/Base, tp %= Base;
}
BigNum operator *(const BigNum &a,const int &b)
{
BigNum ret = a;
if(!a.l || !b){ret.l = 0; return ret;}
for(int i = 1; i <= ret.l; i++) ret.num[i] = a.num[i] * b;
for(int i = 1; i <= ret.l; i++) digit(ret.num[i+1] ,ret.num[i]);
while(ret.num[ret.l+1]) ++ret.l, digit(ret.num[ret.l+1], ret.num[ret.l]);
return ret;
}
BigNum operator +(const BigNum &a,const BigNum &b)
{
BigNum ret = emp; ret.l = std::max(a.l,b.l);
for(int i = 1; i <= ret.l; i++) ret.num[i] = a.num[i] + b.num[i];
for(int i = 1; i <= ret.l; i++) digit(ret.num[i+1] ,ret.num[i]);
if(ret.num[ret.l+1]) ret.l++;
return ret;
}
BigNum operator *(const BigNum &a,const BigNum &b)
{
BigNum ret = emp;
if(!a.l || !b.l){ret.l = 0; return ret;}
ret.l = a.l + b.l - 1;
for(int i = 1; i <= a.l; i++)
for(int j = 1; j <= b.l; j++)
{
ret.num[i+j-1] += a.num[i]*b.num[j];
digit(ret.num[i+1], ret.num[i]);
}
for(int i = 1; i <= ret.l; i++) digit(ret.num[i+1] ,ret.num[i]);
while(ret.num[ret.l+1]) ++ret.l, digit(ret.num[ret.l+1], ret.num[ret.l]);
return ret;
}
void prt(const BigNum &a)
{
printf("%d",a.num[a.l]);
for(int i = a.l-1; i >= 1; i--)
printf("%04d",a.num[i]);
}
int linecnt(int t)
{
return (t<=n)?t:((n<<1)-t);
}
void solve(int x)
{
f[x][0][0].l = f[x][0][0].num[1] = 1;
for(int i = 1; ((i<<1)-x) <= (n<<1); c[x] = i++)
lcnt[i] = linecnt((i<<1)-x);
std::sort(lcnt + 1, lcnt + c[x] + 1);
for(int i = 1; i <= c[x]; i++)
for(int j = 0; j <= k && j <= lcnt[i]; j++)
f[x][i][j] = f[x][i-1][j] + (f[x][i-1][j-1]*(lcnt[i]-j+1));
}
void getans()
{
for(int i = 0; i <= k; i++)
ans = ans + (f[0][c[0]][i]*f[1][c[1]][k-i]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu221.in","r",stdin);
freopen("sgu221.out","w",stdout);
#endif
std::cin >> n >> k;
solve(0), solve(1), getans();
prt(ans);
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。