noip模拟44 solutions

这一场抱零的也忒多了,我也只有45pts

据说好像是把几套题里面最难的收拾出来让我们考得

好惨烈啊,这次的考试我只有第一题骗了40pts,其他都抱零了

T1 Emotional Flutter

这个我直接用线段树维护解集,

这样的,你不能踩到每一个黑块,所以每一个黑块都对应着一个不踩他的范围

我们用线段树维护这些范围的交集,因为值域有点大所以炸了

40pts



#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=5e5+5;
ll T,s,k,n,cnt,a[N],pre[N];
struct XDS{
int mx[N*15],ls[N*15],rs[N*15],laz[N*15];
int seg,rt;
void clear(){seg=0;rt=0;mx[0]=mx[1]=0;}
int newnode(){++seg;ls[seg]=rs[seg]=mx[seg]=laz[seg]=0;return seg;}
void pushup(int x){
mx[x]=max(mx[ls[x]],mx[rs[x]]);
return ;
}
void pushdown(int x){
if(!laz[x])return ;
if(!ls[x])ls[x]=newnode();
if(!rs[x])rs[x]=newnode();
mx[ls[x]]+=laz[x];
mx[rs[x]]+=laz[x];
laz[ls[x]]+=laz[x];
laz[rs[x]]+=laz[x];
laz[x]=0;
return ;
}
void ins(int &x,int l,int r,int ql,int qr){
if(ql>r||qr<l||ql>qr)return ;
if(!x)x=newnode();
if(ql<=l&&r<=qr){
laz[x]++;mx[x]++;
return ;
}
pushdown(x);
int mid=l+r>>1;
if(ql<=mid)ins(ls[x],l,mid,ql,qr);
if(qr>mid)ins(rs[x],mid+1,r,ql,qr);
pushup(x);return ;
}
}xds;
signed main(){
//cout<<(sizeof(xds.mx)*4+sizeof(a)+sizeof(pre)>>20)<<endl;
//xds.mx[1]=10000;cout<<xds.mx[1]<<endl;
scanf("%lld",&T);
while(T--){cnt=0;
scanf("%lld%lld%lld",&s,&k,&n);
for(re i=1;i<=n;i++){
scanf("%lld",&a[i]),pre[i]=pre[i-1]+a[i];
}
for(re i=0;i<=n;i++){
if(i&1)continue;cnt++;
ll tmp=pre[i]%k,l0=-1,r0=-1,l1=-1,r1=-1;
if(a[i+1]+tmp+s<=k){
l0=0,r0=k-a[i+1]-tmp-s;
xds.ins(xds.rt,0,k-1,l0,r0);
}
if(tmp){
l1=k-tmp,r1=min(l1+k-a[i+1]-s,k-1);
xds.ins(xds.rt,0,k-1,l1,r1);
}
}
if(xds.mx[xds.rt]>=cnt)printf("TAK\n");
else printf("NIE\n");
xds.clear();
}
}


其实正解也是有\(log\)的,只不过他的放在了1e5上,而我的放在了1e9*1e5上,并且空间好像也不太够

每次只能跨越k个格,那么我们每次踩到的点在%k意义下都在一个点上

并且这个点不能被任何一个黑块覆盖,所以把所有黑块弄下来

排序,减去没用的,然后去覆盖,如果能找到空缺就是合法的

脚长为s,直接对黑块的长的+s,

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=5e5+5;
ll T,s,k,n,a[N],fro;
struct node{
ll l,r;
node(){}
bool operator < (node x)const{
if(l==x.l)return r>x.r;
return l<x.l;
}
}sca[N];
int cnt,mnt;
signed main(){
scanf("%lld",&T);
while(T--){
cnt=0;mnt=0;fro=0;
scanf("%lld%lld%lld",&s,&k,&n);
//if(k<s){printf("NIE\n");continue;}
bool flag=false;
for(re i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(a[i]+s>k&&(i&1))flag=true;
}
if(flag||k<s){printf("NIE\n");continue;}
//cout<<"Sb"<<endl;
for(re i=1;i<=n;i++){
if((i^1)&1){fro+=a[i];continue;}
a[i]+=s;a[i+1]-=s;
ll pl=(fro+1)%k,pr=(fro+a[i]-1)%k;
//cout<<i<<" "<<pl<<" "<<pr<<endl;
fro+=a[i];
sca[++cnt].l=pl;
if(pr>=pl)sca[cnt].r=pr;
else {
sca[cnt].r=k-1;
sca[++cnt].l=0;
sca[cnt].r=pr;
}
//cout<<i<<" "<<sca[cnt].l<<" "<<sca[cnt].r<<endl;
}
sort(sca+1,sca+cnt+1);mnt=1;
for(re i=2;i<=cnt;i++){
if(sca[i].l>=sca[mnt].l&&sca[i].r<=sca[mnt].r)continue;
sca[++mnt]=sca[i];
}
flag=false;
if(sca[1].l!=0||sca[mnt].r!=k-1)flag=true;
//cout<<flag<<endl;
for(re i=1;i<mnt;i++){
if(sca[i].r+1<sca[i+1].l){
//cout<<i<<endl;
flag=true;
}
if(flag)break;
}
//cout<<sca[1].l<<" "<<sca[mnt].r<<endl;
if(flag)printf("TAK\n");
else printf("NIE\n");
}
}


注意边界问题极其ex

T2 Medium Counting

正解和我考场上想的一样,就是利用后面的大小方案推出前面的方案数

但是我考场上只有一个初步的思路,没有具体的实现出来,所以00000

如果当前字符串短的话,后面补0就行了

然后我们对于当前这一位,我们枚举分界点,看啥时候+1

然后直接记忆化搜索就好啦

dp数组含义:dp[i][j][l][r]表示i位,最小的是c,范围是l-r,的方案数

如果当前这一位被认定为c,那么前面的字符串就不能根据当前这一位来判断

只能用后面的字符来区别他们的大小,这个时候就转移到了下一层

最后小小的判一下边界就行了

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const ll mod=990804011;
ll n,dp[25][28][55][55];
char ch[55][25];
int a[55][25];
ll dfs(int p,int c,int l,int r){
if(dp[p][c][l][r]!=-1)return dp[p][c][l][r];
if(l>r)return dp[p][c][l][r]=1;
if(p>20)return dp[p][c][l][r]=(l==r);
if(c>26)return 0;
dp[p][c][l][r]=dfs(p,c+1,l,r);
//cout<<dp[p][c][l][r]<<endl;
for(re i=l;i<=r;i++){
if((a[i][p]!=c&&a[i][p]!=27)||(a[i][p]==27&&!c))break;
dp[p][c][l][r]=(dp[p][c][l][r]+dfs(p+1,0,l,i)*dfs(p,c+1,i+1,r)%mod)%mod;
}
return dp[p][c][l][r];
}
signed main(){
memset(dp,-1,sizeof(dp));
scanf("%lld",&n);
for(re i=1;i<=n;i++){
scanf("%s",ch[i]+1);
for(re j=1;j<=strlen(ch[i]+1);j++){
if(ch[i][j]=='?')a[i][j]=27;
else a[i][j]=ch[i][j]-'a'+1;
}
}
printf("%lld",dfs(1,0,1,n));
}


T3 Huge Counting

这个又是一个更加恶心的计数题,我真的不想说啥了

还是数位dp,害,气死人了

他们都说挺显然的是可重集排列,呵呵呵,我TM看了半天才看出来

每次选择一个数-1,所以减的顺序就是一个排列,因为好多同一位的减法是相同的,所以可重

那就直接套公式就行了\(\huge\frac{(\sum{x_i})!}{\prod{x_i!}}\)

于是你只需要判断奇偶性就行了(然而我考场上并没有看见mod2)

用那个经典公式\(sum_2(x!)=\frac{x}{2}+\frac{x}{4}+\frac{x}{8}+.....\)

暴力求的话可以拿到40pts的好成绩

40pts

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=15;
const ll mod=990804011;
ll T,k,l[N],r[N],ans,ji[N];
void dfs(int x){
if(x==k+1){
ll tmp=0,sum=0,t=2;
for(re i=1;i<x;i++)tmp+=ji[i];
tmp/=2;while(tmp)sum+=tmp,tmp/=2;
for(re i=1;i<x;i++){
ll now=ji[i]/2;
while(now)sum-=now,now/=2;
}
if(!sum)ans++;
//if(ji[1]!=0)cout<<ji[1]<<endl;
if(ans>mod)ans-=mod;
return ;
}
for(ll i=l[x];i<=r[x];i++){
ji[x]=i-1;dfs(x+1);
}
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&k);ans=0;
for(re i=1;i<=k;i++)scanf("%lld%lld",&l[i],&r[i]);
dfs(1);
printf("%lld\n",ans);
}
}


然后你发现上下两部分,如果加和没有进位的话,他们两个有的2的因子个数是相同的

所以如果想让这些x对答案有贡献,就要让这些x的二进制表示每一位上至多有1个1

所以直接数位do,设dp[i][s]表示第i位,卡边界的情况为s,就是每一个x的

注意不要妄想去卡上下边界,因为数组开不出来,所以要容斥,多步的

我是用dfs实现的容斥系数,也可以用1的个数的奇偶性来确定

直接转移就行了,我是看完题解代码才会的。。。。。。。

转移的时候,我们要先把每一个卡边界的0拿出来,

这时候全是0,方案可行,

再去枚举每一个可能的1,如果卡边界就要把边界卡上,

如果不卡,那就还是原来的边界

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=15;
const ll mod=990804011;
ll T,k,l[N],r[N],ans,ji[N];
ll f[52][1<<10];
ll get_ans(){
memset(f,0,sizeof(f));
f[50][(1<<k)-1]=1;
for(re i=50;i>=1;i--){
for(re j=0;j<(1<<k);j++){
if(!f[i][j])continue;
ll tmp=0;
for(re l=1;l<=k;l++)
if((j>>l-1)&1 && ((ji[l]>>i-1)^1)&1)
tmp|=(1<<l-1);
f[i-1][tmp]=(f[i-1][tmp]+f[i][j])%mod;
for(re l=1;l<=k;l++)
if(((j>>l-1)^1)&1)f[i-1][tmp]=(f[i-1][tmp]+f[i][j])%mod;
else if((ji[l]>>i-1)&1)f[i-1][tmp|(1<<l-1)]=(f[i-1][tmp|(1<<l-1)]+f[i][j])%mod;
}
}
ll ret=0;
for(re i=0;i<(1<<k);i++)ret=(ret+f[0][i])%mod;
return ret;
}
void dfs(int x,int fl){
if(x==k+1){
ans=(ans+get_ans()*fl+mod)%mod;
return ;
}
ji[x]=r[x];
dfs(x+1,fl);
if(l[x]-1>=0){
ji[x]=l[x]-1;
dfs(x+1,-fl);
}
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&k);ans=0;
for(re i=1;i<=k;i++)scanf("%lld%lld",&l[i],&r[i]),l[i]--,r[i]--;
dfs(1,1);
printf("%lld\n",ans);
}
}


T4 字符消除2

说真的,一开始我连题面都没看懂,

后来发现是找到一个和原字符串t集合相同的01串

这样的话,我们先找到所有可行的t

直接用KMP从n向前跳,所有跳出来的数,用n减去它,就是一个可行的t

然后考虑构造这个01串,我们要把KMP匹配到的所有的长度记录下来

如果下一个的长度\(\le\)当前的2倍,那就直接复制过去就行了

不然的话,我就把中间的全干成0,然后再跑一边KMP,看看还是不是原来的匹配

我是直接将之前的p指针记录下来,然后直接跳回去,

如果不是原来的匹配了,就把最后一位换成1

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=2e5+5;
char ch[N];
int T,n,fail[N],p,len[N],cnt;
int nxt[N],pri[N],tot;
void kmp(int l,int r){
for(re i=l;i<=r;i++){
while(pri[i]!=pri[p+1]&&p)p=nxt[p];
if(pri[i]==pri[p+1])p++;
nxt[i]=p;
}
}
signed main(){
scanf("%d",&T);
while(T--){
memset(fail,0,sizeof(fail));
memset(len,0,sizeof(len));
memset(nxt,0,sizeof(nxt));
memset(pri,0,sizeof(pri));
p=cnt=tot=0;
scanf("%s",ch+1);n=strlen(ch+1);
//cout<<"sb"<<endl;
for(re i=2,j=0;i<=n;i++){
while(ch[i]!=ch[j+1]&&j)j=fail[j];
if(ch[i]==ch[j+1])j++;
//cout<<i<<" "<<j<<endl;
fail[i]=j;
}
int now=n;while(now)len[++cnt]=now,now=fail[now];//cout<<now<<endl;
if(len[cnt]>1)pri[len[cnt]]=1;
kmp(2,len[cnt]);
//cout<<"sb"<<endl;
//cout<<p<<endl;
for(re i=cnt-1;i>=1;i--){
if(len[i]>len[i+1]*2){
kmp(len[i+1]+1,len[i]-len[i+1]-1);
int pi=p;
for(re j=1;j<=len[i+1];j++)pri[len[i]-len[i+1]+j]=pri[j];
kmp(len[i]-len[i+1],len[i]);
//for(re j=1;j<=len[i];j++)cout<<pri[j];cout<<endl;
//cout<<nxt[len[i]]<<endl;
if(nxt[len[i]]!=len[i+1]){
p=pi;pri[len[i]-len[i+1]]=1;
kmp(len[i]-len[i+1],len[i]);
}
}
else {
for(re j=len[i+1]+1;j<=len[i];j++)
pri[j]=pri[j-len[i]+len[i+1]];
kmp(len[i+1]+1,len[i]);
}
}
for(re i=1;i<=n;i++)printf("%d",pri[i]);
printf("\n");
}
}


noip模拟44[我想我以后会碰见计数题就溜走的]的更多相关文章

  1. Noip模拟44 2021.8.19

    比较惊人的排行榜 更不用说爆零的人数了,为什么联赛会这么难!!害怕了 还要再努力鸭 T1 Emotional Flutter 考场上没切掉的神仙题 考率如何贪心,我们把黑色的条延长$s$,白色的缩短$ ...

  2. 2021.8.19考试总结[NOIP模拟44]

    T1 emotional flutter 把脚长合到黑条中. 每个黑条可以映射到统一区间,实际操作就是左右端点取模.长度大于$k$时显然不合法. 然后检查一遍区间内有没有不被黑条覆盖的点即可. 区间端 ...

  3. noip模拟44

    A. Emotional Flutter 直接将所有黑块平移到 \([1-k,0]\) 的区间即可,然后找有没有没被覆盖过的整点 注意特判 \(1-k\) 以及 \(0\) 的可行性,考场这里写挂成 ...

  4. [考试总结]noip模拟44

    这个真的是一个 \(nb\) 题. 考试快要结束的时候,在机房中只能听到此起彼伏的撕吼. 啊---------- 然后人们预测这自己的得分. \(\color{red}{\huge{0}}\) \(\ ...

  5. noip模拟赛 好元素 哈希表的第一题

    这是一道关于 题2好元素 2s [问题描述] 小A一直认为,如果在一个由N个整数组成的数列{An}中,存在以下情况: Am+An+Ap = Ai (1 <= m, n, p < i < ...

  6. 【HHHOJ】NOIP模拟赛 玖 解题报告

    点此进入比赛 得分: \(100+20+100=220\)(还不错) 排名: \(Rank\ 16\) \(Rating\):\(+20\) \(T1\):[HHHOJ263]「NOIP模拟赛 玖」三 ...

  7. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  8. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  9. CH Round #54 - Streaming #5 (NOIP模拟赛Day1)

    A.珠 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2354%20-%20Streaming%20%235%20(NOIP模拟赛Day1)/珠 题解:sb题, ...

随机推荐

  1. BUU mrctf shit

    吐槽:去年没写出的题,现在终于可以上手了,昂哥nb 动调发现直接卡着不动了,怀疑是反调试,果然有好几处反调试 这里选择就不先nop了,先让程序跑起来,然后attach,在输入函数下面下个断点,atta ...

  2. 密码学系列之:memory-bound函数

    密码学系列之:memory-bound函数 目录 简介 内存函数 内存受限函数 内存受限函数的使用 简介 memory-bound函数可以称为内存受限函数,它是指完成给定计算问题的时间主要取决于保存工 ...

  3. android开发相关知识笔记

    1.xpage页面打开: openPage(TestFragment.class) openPage("标识") // 页面打开等待结果返回: openPageForResult( ...

  4. Java | Map集合

    Map集合 在现实生活中,有非常多的东西,是和另外一种东西对应的,并且还是唯一的,比如:身份证号与个人,个人与手机,一夫一妻...等,这种关系就是对应关系,又叫做映射.Java为这种数据类型提供了专门 ...

  5. VMware Esxi开通SSH功能

    ESXi 5.5是直接安装在物理主机上的一个虚拟机系统,本质上是一个Linux系统.平时可以通过VMware Client端或者VMware vCenter进行管理,但对于一些特殊的VMware命令或 ...

  6. Luogu P2754 星际转移问题

    Luogu P2754 星际转移问题 思路 首先,对于地球能否到达月球的问题,考虑使用并查集维护. 对于每艘飞船能够到达的站点,放进一个集合里,若两艘飞船的集合有交集,那么就合并两个集合,最后只要地球 ...

  7. Codeforces Round #707 Editorial Div2 题解

    CF1501 Div2 题解 CF1501A 这道题其实是一道英语阅读题,然后样例解释又不清晰,所以我看了好久,首先它告诉了你每个站点的预期到达时间 \(a_i\) ,以及每个站点的预期出发时间 \( ...

  8. Scala学习——函数高级操作

    scala函数高级操作 一.字符串高级操作 多行字符串和插值 package top.ruandb.scala.Course06 object StringApp { def main(args: A ...

  9. 如何进行TIDB优化之Grafana(TiDB 3.0)关注监控指标

    前言 在对数据库进行优化前,我们先要思考一下数据库系统可能存在的瓶颈所在之外.数据库服务是运行在不同的硬件设备上的,优化即通过参数配置(不考虑应用客户端程序的情况下),而实现硬件资源的最大利用化.那么 ...

  10. windows 查看端口号,关闭端口进程

    1.打开cmd,输入:netstat -ano | findstr 8080,根据端口号查找对应的PID.结果如下: 2.根据PID找进程名称,输入命令:tasklist | findstr 1789 ...