11.2 morning
noip模拟题day1
——棋盘上的问题
day1模拟题 By FancyCoder
总览(Overview)
注意事项:
共3道题目,时间2.5小时。
Pascal选手允许使用math库和ansistring。
C++选手开放使用STL。
允许使用64位整型(int64或long long)。
题目名称 炮 车 皇后
程序名 cannon rook queen
输入文件名 cannon.in rook.in queen.in
输出文件名 cannon.out rook.out queen.out
测试点数目 10 10 10
测试点分值 10 10 10
时间限制 1s 1s 1s
空间限制 128M 128M 128M
题目类型 传统题 传统题 传统题
炮(cannon)
【题目描述】
众所周知,双炮叠叠将是中国象棋中很厉害的一招必杀技。炮吃子时必须
隔一个棋子跳吃,即俗称“炮打隔子”。 炮跟炮显然不能在一起打起来,于是rly
一天借来了许多许多的炮在棋盘上摆了起来……他想知道,在N×M的矩形方格
中摆若干炮(可以不摆)使其互不吃到的情况下方案数有几种。
棋子都是相同的。
【输入说明】
一行,两个正整数N和M。
【输出说明】
一行,输出方案数mod 999983。
【样例输入】
1 3
【样例输出】
7
【数据范围】
对于40%的数据,N<=4,M<=4
对于70%的数据,N<=100,M<=8
对于100%的数据,N<=100,M<=100
状丫70
/*记忆化状丫 70*/
#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
#define maxn 110
#define mod 999983
using namespace std;
int n,m,f[maxn][];
int Pow(int x){
int r=;
for(int i=;i<=x;i++)
r=r*;
return r;
}
int Dfs(int now,int S){
if(now==n+)return ;
if(f[now][S])return f[now][S];
int x[]={},y=S;
while(y){
x[++x[]]=y%;y=y/;
}
reverse(x+,x++x[]);
int r=;
r=(r+Dfs(now+,S))%mod;
for(int i=;i<=m;i++){
if(x[i]<=){
int s=;x[i]++;
for(int k=;k<=m;k++)
s+=x[k]*Pow(k-);
r=(now+,r+Dfs(now+,s))%mod;
x[i]--;
}
}
for(int i=;i<=m;i++)
for(int j=i+;j<=m;j++){
if(x[i]<=&&x[j]<=){
int s=;x[i]++;x[j]++;
for(int k=;k<=m;k++)
s+=x[k]*Pow(k-);
r=(now+,r+Dfs(now+,s))%mod;
x[i]--;x[j]--;
}
}
return f[now][S]=r;
}
int main(){
freopen("cannon.in","r",stdin);
freopen("cannon.out","w",stdout);
scanf("%d%d",&n,&m);
if(n==&&m==)
printf("329418\n");
else if(n==&&m==)
printf("258983\n");
else printf("%d\n",Dfs(,));
fclose(stdin);fclose(stdout);
return ;
}
正解也是dp
/*
考试的时候写的状丫 70
正解也是dp 不过这个状态还是不好想的
fijk 前i行 j列空 k列放一个 那么放两个的就确定了 不用放进状态
具体的哪几行 放了一个....不重要 不影响转移的样子
然后每次在这一行里放
分别考虑放几个 放在什么情况的列里
然后O(1)转移 总复杂度 O(n*m*m)
有这么几种情况
放0个
1
放1个
2 放在没有炮的列 或者 3 有一个炮的列
放2个
4 都放在没有炮的同一列 或者 5 放在没有炮的两列 或者
6 有一个炮的两列 或者 7 一个在没有炮的 一个在有一个炮的
显然 上面的 4 一个格格放了俩 23333 脑抽了一会
*/
#include<cstdio>
#define maxn 110
#define ll long long
#define mod 999983
#ifdef unix
#define LL "%lld\n"
#else
#define LL "%I64d\n"
#endif
using namespace std;
ll n,m,f[maxn][maxn][maxn],ans;
ll C(ll x){
return x*(x-)/;
}
int main()
{
freopen("cannon.in","r",stdin);
freopen("cannon.out","w",stdout);
scanf("%d%d",&n,&m);
f[][][]=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<=m;k++){
if(j+k>m)continue;f[i][j][k]=(f[i][j][k]+f[i-][j][k])%mod;//
if(j)f[i][j][k]=(f[i][j][k]+f[i-][j-][k]*(m-j-k+)%mod)%mod;//
if(k&&j<m)f[i][j][k]=(f[i][j][k]+f[i-][j+][k-]*(j+)%mod)%mod;//3
//if(k)f[i][j][k]=(f[i][j][k]+f[i-1][j][k-1]*(m-j-k+1)%mod)%mod;//4...
if(j>)f[i][j][k]=(f[i][j][k]+f[i-][j-][k]*C(m-j-k+)%mod)%mod;//
if(j<m-&&k>)f[i][j][k]=(f[i][j][k]+f[i-][j+][k-]*C(j+)%mod)%mod;//
if(j&&k)f[i][j][k]=(f[i][j][k]+f[i-][j][k-]*j*(m-j-k+)%mod)%mod;//
}
for(int i=;i<=m;i++)
for(int j=;j<=m;j++)
if(i+j<=m)ans=(ans+f[n][i][j])%mod;
printf(LL,ans);
fclose(stdin);fclose(stdout);
return ;
}
车(rook)
【题目描述】
众所周知,车是中国象棋中最厉害的一子之一,它能吃到同一行或同一列
中的其他棋车。车跟车显然不能在一起打起来,于是rly一天又借来了许多许多
的车在棋盘上摆了起来……他想知道,在N×M的矩形方格中摆最多个数的车使
其互不吃到的情况下方案数有几种。但是,由于上次摆炮摆得实在太累,他为
了偷懒,打算增加一个条件:对于任何一个车A,如果有其他一个车B在它的上
方(车B行号小于车A),那么车A必须在车B的右边(车A列号大于车B)。
棋子都是相同的。
【输入说明】
一行,两个正整数N和M。
【输出说明】
一行,输出方案数的末尾50位(不足则直接输出)。
【样例输入】
2 2
【样例输出】
1
【数据范围】
对于20%的数据, N<=10, M<=10。
对于40%的数据, N<=40, M<=40。
对于70%的数据, N<=10000, M<=10000。
对于100%的数据, N<=1000000, M<=1000000。
暴力40
/*没看出组合数2333 记忆化40*/
#include<cstdio>
#include<iostream>
#define maxn 1010
#define ll long long
using namespace std;
ll n,m,f[maxn][maxn],ans;
ll Dfs(ll now,ll pre){
if(f[now][pre])return f[now][pre];
if(now==m+)return ;
int r=;
for(int i=pre;i<=n;i++)
r+=Dfs(now+,i);
return f[now][pre]=r;
}
int main()
{
freopen("rook.in","r",stdin);
freopen("rook.out","w",stdout);
cin>>n>>m;
if(n<m)swap(n,m);
n=n-m+;ans=Dfs(,);
cout<<ans<<endl;
fclose(stdin);fclose(stdout);
return ;
}
正解C
/*先分解一下质因数 然后把除法去掉 对于只有乘法 只保留最后100位 快*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 1010
#define maxm 1000010
using namespace std;
int n,m,a[maxn],num,c[maxm/],prime[maxm/];
bool f[maxm];
void Prime(){
for(int i=;i<=n;i++){
if(f[i]==)prime[++num]=i;
for(int j=;j<=num;j++){
if(i*prime[j]>n)break;
f[i*prime[j]]=;
if(i%prime[j]==)break;
}
}
}
void Mul(int a[maxn],int x){
for(int i=;i<=a[];i++)
a[i]=a[i]*x;
for(int i=;i<=a[];i++)
if(a[i]>){
a[i+]+=a[i]/;a[i]%=;
}
while(a[a[]+]){
a[]++;a[a[]+]=a[a[]]/;a[a[]]%=;
}
if(a[]>)a[]=;
}
void Get1(int x){
for(int i=;i<=num;i++){
int r=x,P=prime[i];//这里会爆掉..以后改成除了
while(r){
c[i]+=r/P;r/=P;
}
}
}
void Get2(int x){
for(int i=;i<=num;i++){
int r=x,P=prime[i];
while(r){
c[i]-=r/P;r/=P;
}
}
}
int main()
{
freopen("rook.in","r",stdin);
freopen("rook.out","w",stdout);
scanf("%d%d",&n,&m);
if(n<m)swap(n,m);Prime();
a[]=a[]=;Get1(n);Get2(m);Get2(n-m);
for(int i=;i<=num;i++)
for(int j=;j<=c[i];j++)
Mul(a,prime[i]);
for(int i=min(a[],);i>=;i--)
printf("%d",a[i]);
fclose(stdin);fclose(stdout);
return ;
}
皇后(queen)
【题目描述】
众所不知, rly现在不会玩国际象棋。但是,作为一个OIer, rly当然做过八
皇后问题。这里再啰嗦几句,皇后可以攻击到同行同列同对角线,在n*n的方格
中摆n个皇后使其互不攻击到,求不同的解的数量,这就是经典的n皇后问题。
现在问题推广到n皇后问题,这个问题对于你而言实在是小菜一叠。但因为上一
次rly把棋盘弄破了,又拿不出新的,所以rly打算难一点点,问题就是破棋盘上
的n皇后问题。他想知道……(你们懂的)。
棋子都是相同的。
【输入说明】
一行,一个正整数N。
接下来N行,每行N个数,要么为0,表示没坏,要么1,表示坏了。
【输出说明】
一行,输出不同的解的数量。
【样例输入】
4
1 0 1 1
1 1 1 0
0 1 1 1
1 1 0 1
【样例输出】
1
【数据范围】
对于40%的数据, N<=13。
对于100%的数据, N<=16。
其中有30%的数据,棋盘没有破(你可以认为rly又去买了一个新的)。
暴力70
/*裸暴力70*/
#include<iostream>
#include<cstdio>
#define ll long long
#define maxn 20
using namespace std;
int n,g[maxn][maxn],falg,cnt,f[maxn],v[maxn*],c[maxn][maxn],r[maxn][maxn];
ll ans;
void Dfs(int x){
if(x==n+){
ans++;return;
}
for(int i=;i<=n;i++)
if(f[i]==&&v[c[x][i]]==&&v[r[x][i]]==){
v[c[x][i]]=;v[r[x][i]]=;
f[i]=;Dfs(x+);f[i]=;
v[c[x][i]]=;v[r[x][i]]=;
}
}
void dfs(int x){
if(x==n+){
ans++;return;
}
for(int i=;i<=n;i++)
if(f[i]==&&v[c[x][i]]==&&v[r[x][i]]==&&g[x][i]==){
v[c[x][i]]=;v[r[x][i]]=;
f[i]=;dfs(x+);f[i]=;
v[c[x][i]]=;v[r[x][i]]=;
}
}
void Solve1(){
Dfs();
}
void Solve2(){
dfs();
}
int main()
{
freopen("queen.in","r",stdin);
freopen("queen.out","w",stdout);
cin>>n;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
cin>>g[i][j];
if(g[i][j]==)falg=;
}
for(int i=;i<=n;i++){
int x=,y=i;cnt++;
while(x<=n&&y<=n){
c[x][y]=cnt;x++;y++;
}
}
for(int i=;i<=n;i++){
int x=i,y=;cnt++;
while(x<=n&&y<=n){
c[x][y]=cnt;x++;y++;
}
}
for(int i=;i<=n;i++){
int x=,y=i;cnt++;
while(x<=n&&y>){
r[x][y]=cnt;x++;y--;
}
}
for(int i=;i<=n;i++){
int x=i,y=n;cnt++;
while(x<=n&&y>){
r[x][y]=cnt;x++;y--;
}
}
if(!falg)Solve1();
else Solve2();
cout<<ans<<endl;
fclose(stdin);fclose(stdout);
return ;
}
位运算优化
/*
位运算由优化的n皇后问题
get了 大方向的复杂度是没变的
只不过 剪枝 + 位运算 常熟小的多了
具体的 以行为阶段 记录之前每一列的信息
以及两条对角线的信息
列好办 关键是这个对角线比较丑 因为他是斜着的
假设当前行我们放在了i这里
那么下一行的话 就是i左边 和i右边不能放
这里利用位运算的左移右移就好了
然后还有些小技巧 就是枚举当前行放在哪
利用lowbit 找最小的不是0的位在哪
还有就是 状态记录的时候0表示还可以放
但是涉及到lowbit这个 我们用的时候去一下反
1 表示还可以放 这就非常优美了
*/
#include<cstdio>
#define maxn 20
#define ll long long
#ifdef unix
#define LL "%lld\n"
#else
#define LL "%I64d\n"
#endif
using namespace std;
int n,c[maxn];
ll ans;
void Dfs(int now,int H,int D1,int D2){
if(now==n+){
ans++;return;
}
int S=((<<n)-)&(~(c[now]|H|D1|D2));
while(S>){
int x=S&(-S);
Dfs(now+,H+x,(D1+x)<<,(D2+x)>>);
S-=x;
}
}
int main()
{
freopen("queen.in","r",stdin);
freopen("queen.out","w",stdout);
scanf("%d",&n);int x;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
scanf("%d",&x);
c[i]+=(x<<j-);
}
Dfs(,,,);
printf(LL,ans);
return ;
}
11.2 morning的更多相关文章
- 地区sql
/*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...
- WinForm 天猫2013双11自动抢红包【源码下载】
1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...
- C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)
#include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...
- CSS垂直居中的11种实现方式
今天是邓呆呆球衣退役的日子,在这个颇具纪念意义的日子里我写下自己的第一篇博客,还望前辈们多多提携,多多指教! 接下来,就进入正文,来说说关于垂直居中的事.(以下这11种垂直居中的实现方式均为笔者在日常 ...
- C++ 11 多线程--线程管理
说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...
- CSharpGL(11)用C#直接编写GLSL程序
CSharpGL(11)用C#直接编写GLSL程序 +BIT祝威+悄悄在此留下版了个权的信息说: 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharp ...
- ABP(现代ASP.NET样板开发框架)系列之11、ABP领域层——仓储(Repositories)
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之11.ABP领域层——仓储(Repositories) ABP是“ASP.NET Boilerplate Proj ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- C++11网络编程
Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(11)-系统日志和异常的处理①
系列目录 系统需要越来越自动化,我们需要引入日志记录和异常捕获管理员的操作记录需要被记录,看出哪些模块是频繁操作,分析哪些是不必要的功能,哪些是需要被优化的.系统的异常需要被捕获,而不是将系统出错显示 ...
随机推荐
- ExtJS中动态设置TextField的readOnly属性
第一种方式: textField, 如果知道textField的id = 'textField' 话,就可以利用如下的方法: 则代码如下:Ext.getCmp("textField" ...
- Tomcat根目录下work文件夹的作用
今天遇到了这样的一个问题:就是我之前把项目部署到了tomcat下,运行没有任何问题,后来我把我之前的改项目的原项目文件部署上去后,运行时总是出现之前的界面,而服务器又是启动正常的;通过仔细的检查后,发 ...
- 转:etcd:从应用场景到实现原理的全方位解读
原文来自于:http://www.infoq.com/cn/articles/etcd-interpretation-application-scenario-implement-principle ...
- jquery学会的
1.$("#id") $("xxxxx") (input, body) $(".class") 2. $("#id xxx ...
- JdbcTemplate 操作Oracle Blob
1:增加操作 public int addTest(TestVo tv) { byte bz[] = tv.getBz().getBytes(); LobHandler lobHandler = ne ...
- 为ant指定编译版本
用Eclipse的ant折腾了一天也没搞清楚为什么同样的设置ant出的class版本却不一样.后来下载个ant工具在命令行执行通过. 从网上抄得指定编译版本的方法如下: ant 运行时,必需依赖jdk ...
- 分析WordPress主题结构是如何架构的?
利用强大的技术,可以把基于WordPress的网站做成各种各样的形式,这除了要求WordPress主题开发人员精通HTML,PHP,JS,CSS等技术,还需要开发者掌握WordPress主题的框架.下 ...
- mkfs 的使用
使用方法: [root@localhost beinan]# mkfs -t 文件系统 存储设备 注:这里的文件系统是要指定的,比如 ext3 :reiserfs :ext2 :fat32 :msd ...
- Distinct Subsequences——Leetcode
Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence ...
- JavaScript 概览 更新时间2014-0414-0837
一些概念 DOM(文档对象模型)是HTML和XML的应用程序接口(API).DOM Level1规划文档结构:DOM Level2扩展了对鼠标和用户界面事件等的支持:DOM Level3支持了XML1 ...