今天比昨天更惨,惨炸了

看到T1不会,跳!!!

T2不会,再跳!!!!

T3不会,后面没题了;;;;

无奈无奈,重新看T1,然鹅时间已经过去了一个小时

然而我一想不出题来就抱着水瓶子喝水,然后跑厕所,然后思路一直断。。。。

但是吧看到题解之后一切就恍然大悟了

哈哈哈哈没事慢慢锻炼,以后的考试一定得上100吧

看到这分数,怎么样,震惊到了吧,倒数第三那个是我,这都是大佬,别看我还有15分,蒙出来的,一点技术含量都没有

T1排序

N<=12;;;;

可以看到这数据属实很小啊

其实考场上我想到了正解,可惜我没敢打,(凭什么这题正解是dfs)那可是深搜啊!!!(暴力象征啊,怎么能是他呢?!?!?!?)

说正解吧;;

可以得到:对于所有操作来说,操作顺序对结果没有任何影响

(哼考场上我发现这个规律了,所以打了个阶乘就走了,没想到还有15pts)

所以我们可以从最小的i开始dfs

首先我们要判断这样的块中有多少不符合规律的(注意当前如果是2x那么判断的时候要判断长度为2x-1的区间(这很显然吧))

有四种情况:

  1、有2个以上的不符合规律的区间。那就没法交换啦,只让交换一次,所以可以直接返回了,00000

  2、没有不符合规律的。那就直接去下一层x+1

  3、有1个不符合规律的区间。那就交换它前后的区间就行了

  4、有2个不符合规律的区间。那么这时候可以两个不符合的互相交换,没准就成了呢(注意交换完了之后要判断,然后再换回去)判断成功后才能进入下一层

再定义一个计数器sum,记录一共交换了多少次

还有dfs的时候别忘了sum++,然后用完之后在sum--;

判断是否符合规律的时候有两种情况:1、前面的比后面的大

                 2、前后的差值大于1(这个我是考后才发现的,原来这个区间里的数是连续的,一开始我还想离散化嘞!!!)

#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=1<<13;
int n,m,nn;
int a[N];
int jc[15],po[15];
int ans,sum;
bool flag(int l,int r){
if(l==r)return true;
for(re i=l+1;i<=r;i++)
if(a[i]<a[i-1]||a[i]-a[i-1]>1)return false;
return true;
}
void swp(int l,int r,int len){
int b[N];
for(re i=0;i<len;i++)b[i]=a[l+i];
for(re i=0;i<len;i++)a[l+i]=a[r+i];
for(re i=0;i<len;i++)a[r+i]=b[i];
}
void dfs(int x){
int num=0;
int p[100];
for(re i=1;i<=po[n];i+=po[x])
if(!flag(i,i+po[x]-1))
p[++num]=i,p[++num]=i+po[x-1];
if(num>4)return ;
if(num==0)
if(x==n)ans+=jc[sum];
else dfs(x+1);
else if(num==2){
sum++;
swp(p[1],p[2],po[x-1]);
if(flag(p[1],p[1]+po[x]-1))
if(x==n)ans+=jc[sum];
else dfs(x+1);
swp(p[1],p[2],po[x-1]);
sum--;
}
else if(num==4){
sum++;
for(re i=1;i<=2;i++){
for(re j=3;j<=4;j++){
swp(p[i],p[j],po[x-1]);
if(flag(p[1],p[1]+po[x]-1)&&flag(p[3],p[3]+po[x]-1))
if(x==n)ans+=jc[sum];
else dfs(x+1);
swp(p[i],p[j],po[x-1]);
}
}
sum--;
}
}
int main(){
scanf("%d",&n);
po[0]=1;jc[0]=1;
for(re i=1;i<=n;i++)jc[i]=jc[i-1]*i,po[i]=po[i-1]*2;
for(re i=1;i<=po[n];i++){
scanf("%d",&a[i]);
}
dfs(1);
printf("%d",ans);
}

Code

T2划艇

这是这场考试中最难的一个题了

考试的时候完全没有思路,想要通过dfs骗来9分没想到爆零了 ,害害害害害

首先想到的一定是dp;

(不对不对不对,首先想到的应该是离散化,毕竟数据范围太大了。。。QAQ)

设f[i][j]表示第i个学校派出j条船所能达到的方案数

啊呀,你突然就发现,这每个学校的a[i]和b[i]达到的区间会有重复的部分啊(完了完了完了转移不了了,然后你就放弃了dp,成功的躲避了正解)

凡事都得试试看啊,不试试就放弃,是不是傻啊

突然你就发现好像可以转移诶

这时候涉及到离散化的时候的一个小细节------------左闭右开(其实左开右闭也可以啦,都是为了让整个区间不重不漏,就看个人习惯了)

将a[i]和b[i]+1塞到离散化数组里,在设计转移方程的时候,注意循环的范围是(<)

转移的时候要分两种情况:

    1、i-1这个学校派出的划艇不在a[i]~b[i]-1中,那么就可以直接转移,此时的i学校可以有方案数就是C(b[i]-a[i],1),那么再乘上前面所有的方案数就好了

  (那么问题来了,怎么得到前面所有的方案数呢。。

   设sum[i][j]表示f[i][j]的二维前缀和,怎么求呢:sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+f[i][j];

   可能这也叫容斥原理吧,把多加上的给剪掉就好了)。

    2、i-1和它以前的学校有一部分派出了在这个区间之内的划艇,那么就要再设一个未知数k,它表示从第k个开始,后面的学校派出了a[i]~b[i]-1只划艇

     这个转移比较难设计,f[i][j]+=组合数*sum[k-1][j-1];这个组合数怎么求呢

   (再引入一个数组,len[ ],表示离散化数组里lsh[i]~lsh[i+1]的长度,(向后lsh[i+1]的长度,而不是向lsh[i-1]的,不然转移方程要修改的)

     首先我们要在了len[i]这么长的区间内寻找k个数(就像在一个递增区间内找k个数递增一样)有C(len[i],k)这么多种选择,当然这其中会有学校不派出划艇

     所以在i-k-1个学校中选出p-2学校来(不包括i和k)C(i-k+1,p-2)这个要乘好多p从1~i-k+1所以要手动搞一下,把它展开在合并,最后变成一个可以边转移边求出来的组合数,乘上就好了

还要注意,sum[i][j],不仅要吧a[i]~b[i]-1的f[i][j]加上,别的地方也要加上

然后我们就可以开开心心的把代码粘上了!!!!

记得开long long哟,不开long long见祖宗哦

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register int
const int mod=1e9+7;
const int N=505;
int n;
int l[N],r[N],len[N*2];
int lsh[N*2],lh,ls[N*2];
int inv[N];
int dp[N][N*2],sum[N][N*2];
map<int,int> p;
signed main(){
scanf("%lld",&n);
inv[1]=inv[0]=1;
for(re i=2;i<=500;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for(re i=1;i<=n;i++){
scanf("%lld%lld",&l[i],&r[i]);
lsh[i*2-1]=l[i];
lsh[i*2]=r[i]+1;
}
sort(lsh+1,lsh+2*n+1);
for(re i=1;i<=2*n;i++){
if(lsh[i]!=lsh[i-1]){
ls[++lh]=lsh[i];
p[lsh[i]]=lh;
}
}
for(re i=1;i<=n;i++){
l[i]=p[l[i]];
r[i]=p[r[i]+1];
}
sum[0][0]=dp[0][0]=1;
ls[lh+1]=ls[lh]+1;
for(re i=1;i<=lh;i++)len[i]=ls[i+1]-ls[i];
for(re i=1;i<=n;i++)sum[i][0]=1;
for(re i=1;i<=lh;i++)sum[0][i]=1;
for(re i=1;i<=n;i++){
for(re j=1;j<l[i];j++)
sum[i][j]=(sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+dp[i][j]+mod)%mod;
for(re j=l[i];j<r[i];j++){
dp[i][j]=sum[i-1][j-1]*len[j]%mod;
int c=len[j]-1;
int can=1;
for(re k=i-1;k>=1;k--){
if(l[k]<=j&&j<r[k]){
can++;
c=c*((can+len[j]-2)*inv[can]%mod)%mod;
dp[i][j]=(dp[i][j]+sum[k-1][j-1]*c%mod)%mod;
}
}
sum[i][j]=(sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+dp[i][j]+mod)%mod;
}
for(re j=r[i];j<=lh;j++)
sum[i][j]=(sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+dp[i][j]+mod)%mod;
}
printf("%lld",sum[n][lh]-1);
}

Code

T3放棋子

感谢赵队一句话点懂了我

二维转移不了就用三维的啊

那么我瞬间感觉自己又行了

设f[i][j][k]为占据i行j列并且放了前k种颜色的棋子的方案数,然后你发现这根本不能直接求出来!!!

所以再设,g[i][j][k]为占据i行j列(这里指的是占满,就是前i行和前j列中哪个格子都不能再放其他种类的棋子了)并且放了k个相同种类的棋子

可以看到f[i][j][k]可以由f[1~i][1~j][ ]转移过来,那么这个式子我打不出来,所以你们自己看代码,总共五层循环!!!

  f[i][j][k]转移的时候要乘组合数,就是空出哪几行和哪几列的方案数,最后要乘上g[i][j][col[k]](col[k]就是输入的第k种棋子的个数)

那么g[i][j][k]咋求嘞,你又有重大发现,这个不能直接求 ------废话!!

还是容斥原理一下呗:g[i][j][k]=C(i*j,k)-g[a][b][k]*C(i,i-a)*C(j,j-b)就是减去那些有空行空列的情况

然后就是代码时间

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int mod=1e9+9;
int n,m,e;
int col[15];
ll f[35][35][15];
ll g[35][35][1005];
ll c[1005][1005];
ll ans;
signed main(){
scanf("%d%d%d",&n,&m,&e);
for(re i=1;i<=e;i++)
scanf("%d",&col[i]);
c[0][0]=1;
for(re i=1;i<=1000;i++){
c[i][0]=c[i][i]=1;
for(re j=1;j<i;j++){
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
for(re i=1;i<=n;i++)
for(re j=1;j<=m;j++)
for(re k=max(i,j);k<=i*j;k++){
g[i][j][k]=c[i*j][k];
for(re a=1;a<=i;a++)
for(re b=1;b<=j;b++){
if(a*b<k||(a==i&&b==j))continue;
g[i][j][k]=(g[i][j][k]-g[a][b][k]*c[i][a]%mod*c[j][b]%mod+mod)%mod;
}
}
f[0][0][0]=1;
for(re i=1;i<=n;i++)
for(re j=1;j<=m;j++){
for(re k=1;k<=e;k++){
if(i*j<col[k])continue;
for(re a=0;a<=i;a++)
for(re b=0;b<=j;b++)
if((i-a)*(j-b)>=col[k])
f[i][j][k]=(f[i][j][k]+f[a][b][k-1]*c[n-a][i-a]%mod*c[m-b][j-b]%mod*g[i-a][j-b][col[k]]%mod)%mod;
}
ans=(ans+f[i][j][e])%mod;
}
printf("%lld",ans);
}

完结

∑l=1i−1∑r=1j−1f[l][r]+∑l=1k−1∑r=1j−1f[l][

2021.5.23 noip模拟2(排序|划艇|放棋子)的更多相关文章

  1. 2021.5.22 noip模拟1

    这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...

  2. 9.23 noip模拟试题

      Problem 1 抓牛(catchcow.cpp/c/pas) [题目描述] 农夫约翰被通知,他的一只奶牛逃逸了!所以他决定,马上出发,尽快把那只奶牛抓回来. 他们都站在数轴上.约翰在N(O≤N ...

  3. 10.23 noip模拟试题

    尼玛蛋pdf好难粘 直接写了 T1 /*开始写wa了 我真弱2333 关于p的排序规则不只是差值 为了字典序最小 还要拍别的*/ #include<cstdio> #include< ...

  4. 2018.10.23 NOIP模拟 “新”的家园(缩图+dijksta/spfa)

    传送门 考试70分骗分写挂了=30分=全场最低. 哎今天230垫底了. 这题出的挺好. 对于非关键点直接缩点. 每次把要查的insertinsertinsert进缩好的图里面跑spfa/dijkstr ...

  5. 2018.10.23 NOIP模拟 行星通道计划(bit)

    传送门 卡常题. 成功卡掉了作死写树套树的zxy. 然而对我的二维bit无能为力. 直接维护两棵bit. bit1[i][j]bit1[i][j]bit1[i][j]表示左端点小于等于iii,右端点小 ...

  6. 2018.10.23 NOIP模拟 战争(并查集)

    传送门 跟bzoj1015: [JSOI2008]星球大战是同一道题啊讲道理. 随便合并一下就能过了. 代码

  7. 9.23 NOIP模拟题(数学专练)

    数论基础 专题测试  命题人:清华大学 王赢绪 /* 水题 答案为C(n-k,m-1) 预处理阶乘和逆元,O(1)算答案 开始读错题了!!!朱一乐!!! */ #include<iostream ...

  8. noip模拟赛 排序

    分析:因为序列是不严格单调的,所以挪动一个数其实就相当于把这个数给删了.如果a[i] < a[i-1],那么可以删掉a[i],也可以删掉a[i-1](!如果没考虑到这一点就只有90分),删后判断 ...

  9. 【noip模拟赛8】魔术棋子

    描述 在一个M*N的魔术棋盘中,每个格子中均有一个整数,当棋子走进这个格子中,则此棋子上的数会被乘以此格子中的数.一个棋子从左上角走到右下角,只能向右或向下行动,请问此棋子走到右下角后,模(mod)K ...

随机推荐

  1. hdu4020简单想法题

    题意:       给你一些人,这些人有很多广告,每个广告有自己的点击率和长度,每次有m组询问,问每个人点击率前K名的广告的总长度是多少. 思路:       数据很大,很容易超时,总的想法还是先so ...

  2. IDAPython类库---idautils.py的源码

    #--------------------------------------------------------------------- # IDAPython - Python plugin f ...

  3. 路由协议之OSPF

    目录 OSPF协议 OSPF的七种状态 OSPF的11种LSA Stub和Nssa OSPF中的防环机制 OSPF中的路由汇总和路由过滤 OSPF中的虚拟链路 虚拟链路有两种存在的意义 OSPF中的认 ...

  4. 子域名查询、DNS记录查询

    目录 子域名信息查询 Layer子域名爆破机 subDomainBrute 利用google查询 HTTP证书查询 DNS记录查询脚本 IP转换为经纬度 利用网页获取对方经纬度信息 首先关于DNS域名 ...

  5. 使用QT creator实现一个五子棋AI包括GUI实现(8K字超详细)

    五子棋AI实现 五子棋游戏介绍 五子棋的定义 五子棋是全国智力运动会竞技项目之一,是具有完整信息的.确定性的.轮流行动的.两个游戏者的零和游戏.因此,五子棋是一个博弈问题. 五子棋的玩法 五子棋有两种 ...

  6. 【python】Leetcode每日一题-前缀树(Trie)

    [python]Leetcode每日一题-前缀树(Trie) [题目描述] Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的 ...

  7. solidworks中 toolbox调用出现未配置的解决方法

    解决步骤:1:win7卸载安全补丁:KB3072630 WIN10,忽略.2:关闭所有Solidworks的进程3:CMD命令行进入:cd c:\program files\solidwokrs co ...

  8. 5分钟,教你用Python每天跟女朋友说1000遍土味情话!

  9. 使用花生壳、瑞友天翼远程访问金蝶K3

    金蝶版本号 WISE15.1 瑞友6.0系列 花生壳5 金蝶软件无法通过外网直接访问 因此需要使用瑞友天翼来实现远程访问 一般来说 金蝶服务器固定了IP地址以后 通过路由器开房两个外网端口即可实现瑞友 ...

  10. WPF使用自定义Main函数

    一.自定义Main函数 在WPF中,我们添加一个Program静态类,添加一个Main静态方法,需要注意的是该方法需要添加"STAThread",表示WPF程序需运行在单一线程单元 ...