UVA 11806 Cheerleaders (容斥原理+二进制枚举)
2016-04-02 21:48
316 查看
UVA 11806 Cheerleaders (容斥原理+二进制枚举) :http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110771#problem/G 传送门:nefu
题目大意:
往一个n*m的格子内部放k个石子,要求四个边上必须都有,求所有放置石子的方法数。
题目分析:
由于正常去做需要考虑的情况种类数比较多,所以我们反过来考虑。设往一个n*m的格子中任意存放k个石子的方法数,设为全集S,设集合A表示:第一行没有石子的方法数,集合B表示:最后一行没有石子的方法数,集合C表示:第一列没有石子的方法数,集合D表示:最后一列没有石子的方法数,根据容斥原理,满足题意的方法数共有|S-(A并B并C并D)|,即全集减去第一行或者最后一行或者第一列或者最后一列没有石子的方法数。
此题比较有技巧性的方面还体现在应用了二进制枚举和组合数的打表。
代码实现:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Mod=1000007;
int c[510][510];
void Uint()
{
memset(c,0,sizeof(c));
c[0][0]=1;
for(int i=0;i<=500;i++)
{
c[i][0]=1;
c[i][i]=1;
for(int j=1;j<i;j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod;
}
}
}
int main()
{
int t,n,m,k;
int casenum=0;
Uint();
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&m,&n,&k);
int sum=0;
for(int w=0;w<16;w++) //二进制枚举,由于有四个集合,所以要枚举到16
{
int b=0,cc=m,r=n;
if(w&1)
{
b++;
cc--;
}
if(w&2)
{
b++;
cc--;
}
if(w&4)
{
b++;
r--;
}
if(w&8)
{
b++;
r--;
}
if(b&1)
{
sum=(sum-c[cc*r][k]+Mod)%Mod;
}
else
{
sum=(sum+c[cc*r][k])%Mod;
}
}
printf("Case %d: %d\n",++casenum,sum);
}
return 0;
}
题目大意:
往一个n*m的格子内部放k个石子,要求四个边上必须都有,求所有放置石子的方法数。
题目分析:
由于正常去做需要考虑的情况种类数比较多,所以我们反过来考虑。设往一个n*m的格子中任意存放k个石子的方法数,设为全集S,设集合A表示:第一行没有石子的方法数,集合B表示:最后一行没有石子的方法数,集合C表示:第一列没有石子的方法数,集合D表示:最后一列没有石子的方法数,根据容斥原理,满足题意的方法数共有|S-(A并B并C并D)|,即全集减去第一行或者最后一行或者第一列或者最后一列没有石子的方法数。
此题比较有技巧性的方面还体现在应用了二进制枚举和组合数的打表。
代码实现:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Mod=1000007;
int c[510][510];
void Uint()
{
memset(c,0,sizeof(c));
c[0][0]=1;
for(int i=0;i<=500;i++)
{
c[i][0]=1;
c[i][i]=1;
for(int j=1;j<i;j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod;
}
}
}
int main()
{
int t,n,m,k;
int casenum=0;
Uint();
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&m,&n,&k);
int sum=0;
for(int w=0;w<16;w++) //二进制枚举,由于有四个集合,所以要枚举到16
{
int b=0,cc=m,r=n;
if(w&1)
{
b++;
cc--;
}
if(w&2)
{
b++;
cc--;
}
if(w&4)
{
b++;
r--;
}
if(w&8)
{
b++;
r--;
}
if(b&1)
{
sum=(sum-c[cc*r][k]+Mod)%Mod;
}
else
{
sum=(sum+c[cc*r][k])%Mod;
}
}
printf("Case %d: %d\n",++casenum,sum);
}
return 0;
}
相关文章推荐
- 最近公共祖先 LCA Tarjan算法
- Android中的羊角符
- 观察者模式——JavaScript
- hdu-5655 CA Loves Stick(水题)
- POJ 3280 Cheapest Palindrome
- OPENCV 函数cvCreateMat
- 体验VS2015 Update 2 的 Android 和 Python
- ios视图frame和bounds的对比
- HDU 1024 Max Sum Plus Plus --- dp+滚动数组
- NFS服务的配置(redhat liunx 7.0)
- 杭电1518
- 程序员必备素质-团队
- 随笔:异类&天才
- Chrome代理设置
- 【配置安装】Xamarin for Windows, 用C#开发android
- 进程描述与创建
- 内部类 & 泛型
- Android导入工程提示 Invalid project description 详解
- 使用实体组件系统(ECS)开发”吃方块”游戏实例分析
- 在windows server 2008上搭建ldap服务