简单的区间

$update$

终于$AC$了

找到$(sum[r]+sum[l](sum表示以中间点为基准的sum)-mx)\%k==0$的点

注意这里$sum$表示是以$mid$为基准点,(即$sum[l]$为后缀和,$sum[r]$为前缀和)

回忆$(sum[r]-sum[l])\%k==0$这个经典问题做法(入阵曲简化版),开桶,桶里维护$sum[l]\%k$,那么$r$贡献就是桶里$sum[r]\%k$个数

于是这个题开桶维护$sum$,问题转化为求$max$即可

记录$max$位置是否$>mid$,区别对待

设$f[i][0]$表示$max$在$mid$右面,$f[i][1]$表示$max$在$mid$左面

$f[i][0]$存下右面$sum[r]-mx$,找桶里是否存在左面$sum[l]$
$f[i][1]$存下右面$sum[r]$ 找到左面是否存在$mx-sum[l]$
完了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
ll f[A][2],a[A],pos[A],mx[A],sum[A];
ll cnt,n,k,ans;
void solve(ll l,ll r){if(l==r) return ;ll mid=(l+r)>>1;cnt=sum[mid]=mx[0]=0;for(ll i=mid+1;i<=r;i++){if(a[i]>a[mx[cnt]]) mx[++cnt]=i;sum[i]=(sum[i-1]+a[i])%k;f[(sum[i]-a[mx[cnt]]%k+k)%k][0]++;pos[i]=mx[cnt];
//        printf("f[%lld]=%lld  sum=%lld cnt=%lld\n",(sum[i]-a[mx[cnt]]%k+k)%k,f[(sum[i]-a[mx[cnt]]%k+k)%k][0],sum[i],cnt);
    }mx[cnt+1]=r+1;ll suml=0,rnow=mid+1,mxl=0,p=1;for(ll i=mid;i>=l;i--){suml=(suml+a[i])%k;mxl=max(mxl,a[i]);while(p<=cnt&&a[mx[p]]<=mxl) p++;while(rnow<mx[p]) {f[(sum[rnow]-a[pos[rnow]]%k+k)%k][0]--;f[sum[rnow]%k][1]++;rnow++;}
//        printf("ans=%lld f[%lld][1]=%lld p=%lld rnow=%lld mx[%lld]=%lldsum[%lld]=%lld\n",ans,(k+mxl%k-suml)%k,f[(k+mxl%k-suml)%k][1],p,rnow,p,mx[p],rnow,sum[rnow]);ans+=f[(mxl-suml+k)%k][1];if(p<=cnt) ans+=f[(k-suml)%k][0];
//        printf("ans=%lld f[%lld][0]=%lld\n",ans,k-suml,f[(k-suml)%k][0]);
    }for(ll i=mid+1;i<rnow;i++)f[sum[i]][1]--;for(ll i=rnow;i<=r;i++)f[(sum[i]-a[pos[i]]%k+k)%k][0]--;solve(l,mid);solve(mid+1,r);
}
int main(){scanf("%lld%lld",&n,&k);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);solve(1,n);printf("%lld",ans);
}

View Code

简单的玄学

题解

题目中说至少两个相同那么答案就所有方案-全不相同

所有方案${(2^n)}^m=2^{n*m}$,

互不相同,首先第一个随便选剩下避开已经选过就行$2^n*2^{n-1}......2^{n-m+1}$

那么题目很傻逼的让你取模并且约分,你需要先约分再取模(取模再约分的话这个题就太水了,所以是先约分再取模)

思考怎么约分

下面全是$2$多少次方,于是我们看上面多少个二就行了

$2^n*(2^{n}-1)......({2^n}-m+1)$很恶心,思考转化

性质:$2^n-x$中二个数$=$$x$中二的个数

证明:假设$x$可以表示为$j*(2^w)$(j可以是分数),乘法分配率$2^w*(2^{n-w}-j)$后面这个里面没有别的$2$因子了,原式$=$$2^w$,又$j$中没有$2$因子故相乘因子数不变,得证

那么原式就变成求$(m-1)!$里$2$因子数

可以简单求

    for(ll i=1;(1ll<<i)<=m-1;i++){(ercnt+=(m-1)/(1ll<<i));}

例如$1$ $2$ $3$ $4$ $5$ $6$ $7$ $8$这个序列

分别有$(2^1)*2$,$(2^2)*1$,$(2^3)*1$那么就是$8/8+8/4+8/2$

可以看作$/2$时给所有有$2$因子填上一个二(即$2$,$4$,$6$,$8$中填一个2),此时$4$还剩$1$个没填$8$还剩$2$个没填

$/4$给$4$,$8$里填此时$8$还剩$1$个没填

最后$/8$,全部填满

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e6+3;
const ll phi=1e6+2;
ll x,y,n,m;
ll meng(ll x,ll k){ll ans=1;for(;k;k>>=1,x=x*x%mod)if(k&1)ans=ans*x%mod;return ans;
}
ll gcd(ll x,ll y){if(y==0) return x;return gcd(y,x%y);
}
int main(){
//    freopen("sd.txt","w",stdout);scanf("%lld%lld",&n,&m);
/*    if(log(m)>n){printf("1 1\n");return 0;}
*/    ll maxn=meng(2,n%phi);y=meng(maxn,m%phi);x=1;ll ercnt=n;    for(ll i=0;i<m;i++){
//        printf("maxn-i=%lld i=%lld m=%lld x=%lld\n",maxn-i,i,m,x);x=x*(maxn-i)%mod;if(!x) break;}//2逆元500002for(ll i=1;(1ll<<i)<=m-1;i++){(ercnt+=(m-1)/(1ll<<i));printf("ercnt=%lld 1<<=%lld\n",ercnt-n,1ll<<i);}y=y*meng(500002,ercnt)%mod;x=x*meng(500002,ercnt)%mod;printf("%lld %lld\n",(y-x+mod)%mod,y);
}

View Code

简单的填数

题解

一个$up$代表填的上界,$down$代表填的下界

先不考虑已经填了的

$up$两位一进,$down$五位一进

考虑已经填的

先考虑上界

若$a[i]>up$比上界大肯定不合法

若$a[i]=up$取$min(2,up)$

若$a[i]<up$则将$up$调整到$a[i]$次数变为$2$

下界类似

若$a[i]<down$比下界小不合法

若$a[i]>down$将$down$调整到$a[i]$

统计答案时反着扫

序列为什么不是$up$呢

7
0 0 0 2 0 2 0
正解
2
1 1 2 2 2 2 2
用up:
2
1 1 2 2 3 2 2 

代码

/*
7
0 0 0 2 0 2 0
hack
2
1 1 2 2 2 2 2
up:
2
1 1 2 2 3 2 2
10f
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
struct node {ll cnt,x;
}up[A],down[A];
ll n;
ll a[A],tong[A];
int main(){
//    freopen("da.in","r",stdin); freopen("ans.bf","w",stdout);scanf("%lld",&n);for(ll i=1;i<=n;i++){scanf("%lld",&a[i]);}if(a[1]!=1&&a[1]!=0){printf("-1\n");return 0;}up[1].cnt=1,up[1].x=1;down[1].cnt=1,down[1].x=1;for(ll i=2;i<=n;i++){up[i]=up[i-1],down[i]=down[i-1];if(++up[i].cnt>2) up[i].cnt=1,up[i].x++;if(++down[i].cnt>5) down[i].cnt=1,down[i].x++;if(a[i]){if(up[i].x>a[i]){up[i].x=a[i];up[i].cnt=2;}else if(up[i].x==a[i]){up[i].cnt=min(up[i].cnt,2ll);}if(down[i].x<a[i])down[i].x=a[i],down[i].cnt=1;if(up[i].x<a[i]||down[i].x>a[i]){printf("-1\n");return 0;}}}if(up[n].cnt==1){up[n].x=up[n-1].x;}if(up[n].x<down[n].x){printf("-1\n");return 0;}printf("%lld\n",up[n].x);tong[up[n].x]=1;a[n]=up[n].x;for(ll i=n-1;i>=1;i--){if(!a[i]){ll t=min(a[i+1],up[i].x);if(tong[t]==5) t--;a[i]=t;}tong[a[i]]++;}for(ll i=1;i<=n;i++){printf("%lld ",a[i]);}
}

View Code

简单的序列

这是一个简单$dp$,但我觉得很棒在此写下题解

真的非常简单,

有一个长度$n$括号序列(只有$"()"$ ),给定其中长度为$m$一段,求满足括号匹配方案数

$n,m<=1e6$ $n-m<=4000$

题解

性质:我们发现一个合法匹配序列左扩号时刻比右括号多(显然),最后左扩号数量等于右括号数量

设$f[i][j]$表示长度为$i$序列,左扩号比右括号多$j$个方案数

那么类似的设$g[i][j]$为右括号比左扩号多$j$的方案数

(其实$f$和$g$值完全一样)

转移非常简单

当前括号可能是$($则贡献$f[i][j]=f[i-1][j-1]$为$)$则$f[i][j]=f[i-1][j+1]$

总贡献$f[i][j]=f[i-1][j-1]+f[i-1][j+1]$

类似的$g[i][j]=g[i-1][j-1]+g[i-1][j+1]$

那么思考统计答案

其实也非常简单

枚举第一段长度$i$,第一段左扩号比右括号多$j$,设给定序列左扩号比右括号多$j$

$ans=\sum\limits_{i=1}^{i<=n-m} \sum\limits_{j=0}^{j<=i} f[i][j]*g[(n-m)-i][j+tot]$

注意判是否合法

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 4040
const ll mod=1e9+7;
char c[2020202];
ll f[A][A];
ll tot,mint,n,m,ans;
int main(){
//    freopen("da.in","r",stdin); freopen("ans.bf","w",stdout);scanf("%lld%lld",&n,&m);scanf("%s",c+1);for(ll i=1;i<=m;i++){if(c[i]=='(')tot++;else tot--;if(i==1) mint=tot;else mint=min(mint,tot);}f[0][0]=1;for(ll i=1;i<=n-m;i++){for(ll j=0;j<=i;j++){if(j==0) f[i][j]=f[i-1][j+1];else f[i][j]=(f[i-1][j+1]+f[i-1][j-1])%mod;}}for(ll i=0;i<=n-m;i++){for(ll j=0;j<=i;j++){if(j+mint>=0&&j+tot<=n-m)ans=(ans+f[i][j]*f[(n-m)-i][j+tot]%mod)%mod;}}printf("%lld\n",ans);
}

View Code

我没数据,也没法提交,和$std$对拍了一下

下面是我的数据生成及对拍

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     system("g++ bf.cpp -o bf");
 5     system("g++ sol.cpp -o sol");
 6     system("g++ da.cpp -o da");
 7     int rp=0;
 8     while(++rp){
 9         cout<<rp<<" ";
10         system("./da");
11         system("./sol");
12         system("./bf");
13         if(system("diff -B -b ans.sol ans.bf")){
14             puts("WA");
15             while(1);
16         }
17         puts("AC");
18     }
19 }

对拍

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     freopen("da.in","w",stdout);
 5     srand(time(NULL));
 6
 7     int m=rand()%10000+300;
 8     int c=rand()%m+1;
 9     while(m-c>2000){
10         c=rand()%m+1;
11     }
12     cout<<m<<" "<<c<<endl;
13     for(int i=1;i<=c;i++){
14         if(rand()%2){
15             printf("(");
16         }
17         else printf(")");
18     }
19     cout<<endl;
20 }

数据生成

转载于:https://www.cnblogs.com/znsbc-13/p/11474038.html

NOIP模拟测试「简单的区间·简单的玄学·简单的填数·简单的序列」相关推荐

  1. NOIP模拟测试19「count·dinner·chess」

    反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...

  2. NOIP模拟测试7「方程的解·visit」

    visit 由于一些不可预知的错误导致我一直WA 错误最后说 思路 方案一 假设终点在出发点右上方(这样假设只是为了方便) 假设向左走了a步,向右下了b布,那么相应的我们要向右走m+a,向上n+b步 ...

  3. 8.19 NOIP模拟测试26(B) 嚎叫响彻在贪婪的厂房+主仆见证了 Hobo 的离别+征途堆积出友情的永恒...

    T1 嚎叫响彻在贪婪的厂房 以前做过一个等比数列的题「序列」,这个类似 是等差数列且公差不为1的条件就是各项差的绝对值的$gcd!=1$,每次拿出序列前两个数,求出差值,插入到set里,每次向后扩展, ...

  4. [NOIP模拟测试37]反思+题解

    一定要分析清楚复杂度再打!!!窝再也不要花2h20min用暴力对拍暴力啦!!! 雨露均沾(滑稽),尽量避免孤注一掷.先把暴力分拿全再回来刚正解. 即使剩下的时间不多了也优先考虑认真读题+打暴力而非乱搞 ...

  5. NOIP模拟测试10「大佬·辣鸡·模板」

    大佬 显然假期望 我奇思妙想出了一个式子$f[i]=f[i-1]+\sum\limits_{j=1}^{j<=m} C_{k \times j}^{k}\times w[j]$ 然后一想不对得容 ...

  6. NOIP模拟测试39,思维禁锢专场「工业题·玄学题·卡常题」

    工业题 题解 抱歉,题解没时间写了 代码 #include<bits/stdc++.h> using namespace std; #define ll long long #define ...

  7. NOIP模拟测试30「return·one·magic」

    magic 题解 首先原式指数肯定会爆$long$ $long$ 首先根据欧拉定理我们可以将原式换成$N^{\sum\limits_{i=1}^{i<=N} [gcd(i,N)==1] C_{G ...

  8. NOIP模拟测试21「折纸·不等式」

    折纸 题解 考试时无限接近正解,然而最终也只是接近而已了 考虑模拟会爆炸,拿手折纸条试一试,很简单 考你动手能力 代码 #include<bits/stdc++.h> using name ...

  9. NOIP模拟测试17「入阵曲·将军令·星空」

    入阵曲 题解 应用了一种美妙移项思想, 我们先考虑在一维上的做法 维护前缀和$(sum[r]-sum[l-1])\%k==0$可以转化为 $sum[r]\% k==sum[l-1]\%k$开个桶维护一 ...

最新文章

  1. Android ViewGroup事件分发机制
  2. java compare 返回值_关于Java你不知道的那些事之Java8新特性[Lambda表达式和函数式接口]...
  3. 唐僧肉长生不老到底隐藏了哪些骗局?唐僧的妈妈真的吃过唐僧肉吗?
  4. 【ElasticSearch】ElasticSearch在数十亿级别数据下,如何提高查询效率? 性能优化
  5. Pytorch 编译cpp、cuda扩展遇到的问题
  6. 基于 Docker 中的 MongoDB 授权使用
  7. MySQL 第二次练习(源码安装、数据库和表的建立)
  8. NATS_11:NATS集群构建与验证
  9. apache url路由配置重写
  10. MatLab深度学习入门
  11. 基于SEIR的传播动力学模型
  12. 期权定价 - BS模型 - 维纳过程和伊藤引理
  13. usaco 1.1 greedy gift givers
  14. 爱可生 mysql监控_actiontech-zabbix-mysql-monitor
  15. android优化最强软件,手机提速谁最行?十款安卓优化软件比拼
  16. https域名安全证书怎么配置
  17. 马云谈大数据:数据时代的“五个新” 做好准备
  18. 微型计算机接口与技术答案,《微机原理与接口技术》课后习题答案
  19. Planetary Computer——Global Flood Maps全球洪水数据集
  20. 实用软件工程课后答案 (张海潘 吕云翔)

热门文章

  1. Mach 微内核的命名趣闻
  2. Linux 命令之 chown -- 用来变更文件或目录的拥有者或所属群组
  3. Java程序开发三步骤:编写、编译、运行
  4. php hash代码下载,PHP中的哈希表 hash_insert
  5. 怎么更换默认路径_更改电脑桌面路径
  6. python字典编码_python中包含UTF-8编码中文的列表或字典的输出
  7. java 对线程进行事务控制_Java 多线程事务回滚 ——多线程插入数据库时事务控制...
  8. 【WebRTC---序篇】(二)Windows平台WebRTC源码编译
  9. 【OpenGL从入门到精通(二)】绘制一个点
  10. python解析http数据包_如何在python中嗅探HTTP数据包?