noip模拟42
A. 卷
发现乘积足以爆 \(long\) \(long\),但是数据随机,可以略忽略精度问题
一个快速降低数的级别的方法是取对数,由于有性质 \(log(x * y)=logx+logy\),合并时运算会很方便,于是转化成加和型最大独立集问题
B. 简单题
观察发现对于每个奇数,其 \(2\) 倍放在另一个集合,\(4\) 倍放在当前集合,以此类推
那么对于一条偶数长度的链,一定一半放在第一个集合,另一半放在第二个集合,对答案贡献乘 \(2\)
对于奇数长度的链,一定分成 \(len\) 和 \(len+1\) 两部分,那么这样最终答案一定有可行区间 \([l,r]\),那么多出 \(l\) 的部分一定是若干个奇数链造成的,而奇数链又是自由组合,设总数为 \(tot\),答案为 \(\binom{tot}{m-l}\)
发现组合数数过大,模数很小,可以用 \(lucas\) 定理计算
对于计算奇偶链的个数,考虑枚举链长,这是 \(log\) 级别的,那么长度的 \(k\) 的链的起点范围为 \(\displaystyle[\frac{n}{2^{k-1}}+1,\frac{n}{2^k}]\),因为这个不分奇数,得除以 \(2\)
代码实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=5005;
const int maxm=11000025;
const int mod=10000019;
int n,q,x,tot1,tot2,l,r,frac[maxm],inv[maxm],ans,ans1,len;
int po(int a,int b=mod-2){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
void pre(){
frac[0]=1;
for(int i=1;i<=mod-1;i++)frac[i]=frac[i-1]*i%mod;//,cout<<frac[i]<<" ";
inv[mod-1]=po(frac[mod-1]);
// cout<<frac[mod]<<" "<<inv[mod]<<endl;
for(int i=mod-2;i>=0;i--)inv[i]=(i+1)*inv[i+1]%mod;//,cout<<inv[i]<<" ";
return ;
}
int C(int n,int m){
if(n<m)return 0;
if(n==m)return 1;
return frac[n]*inv[m]%mod*inv[n-m]%mod;
}
int lucas(int x,int y){
// cout<<"hhh "<<x<<" "<<y<<endl;
if(x==y)return 1;
if(x<y)return 0;
if(x<mod&&y<mod)return C(x,y);
return lucas(x/mod,y/mod)*C(x%mod,y%mod)%mod;
}
signed main(){
// cout<<po(2);
n=read();
q=read();
pre();
// cout<<C(6,2)<<endl;
len=log2(n)+1;
// cout<<len<<endl;
for(int i=1;i<=len;i++){
// cout<<i<<endl;
int po1=pow(2,i-1);
int po2=pow(2,i);
int up=n/po1;
int down=n/po2+1;
if(down&1)down--;
if(up&1)up++;
int num=(up-down)/2;
if(i&1){
tot1+=num;
}
else tot2+=num;
l+=num*(i/2);
}
r=l+tot1;
// cout<<tot1<<" "<<tot2<<" "<<l<<" "<<r<<endl;
ans1=po(2,tot2);
// cout<<"ppp "<<endl;
for(int i=1;i<=q;i++){
x=read();
if(x<l||x>r){
puts("0");
continue;
}
ans=ans1*lucas(tot1,x-l)%mod;
printf("%d\n",ans);
}
return 0;
}
C. 粉丝
这道题本质是自然数拆分,运用根号分治优化
首先自然数拆分有两种 \(dp\) 方法:
设 \(f[i][j]\) 表示 \(dp\) 到 \(i\) 这个数和为 \(j\) 的方案数,\(f[i][j]=f[i-1][j]+f[i][j-i]\)
\(g[i][j]\) 表示分成了 \(i\) 个数字,和为 \(j\) 的方案数
发现两种 \(dp\) 单独做都是 \(n^2\) 的
但是观察第一种 \(dp\) 的状态是 \(dp\) 到 \(i\) 这个数,值域越小复杂度越低
第二种状态是分成 \(i\) 个数,值域越大复杂度越低
于是在 \(\sqrt n\) 处分治,值域小的部分用第一种,大的部分用第二种,总复杂度为 \(n\sqrt n\)
注意第二种 \(dp\) 其实是每个选了了的数都已经以 \(sq\) 为基准了,那么实际的总和需要加上 \(num*sq\),这个合并时用 \(num\) 记录
代码实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e5+5;
int x,y,n,mod,f[maxn],g[maxn],sum[maxn],sq,ans;
int dp(int limit){
memset(f,0,sizeof f);
memset(g,0,sizeof g);
memset(sum,0,sizeof sum);
ans=0;
f[0]=1;
sq=max((int)sqrt(n),limit);
for(int i=limit;i<sq;i++){
for(int j=i;j<=n;j++){
f[j]+=f[j-i];
f[j]%=mod;
}
}
g[0]=1;
sum[0]=1;
for(int i=1;i<=n/sq;i++){
int t=i*sq;
for(int j=i;j+t<=n;j++){
g[j]=(g[j]+g[j-i])%mod;
}
for(int j=0;j+t<=n;j++){
sum[j+t]+=g[j];
sum[j+t]%=mod;
}
}
for(int i=0;i<=n;i++){
ans=(ans+f[i]*sum[n-i]%mod)%mod;
}
return ans;
}
signed main(){
cin>>x>>y>>n>>mod;
cout<<(dp(x)-dp(y+1)+mod)%mod;
return 0;
}
D. 字符串
首先可以把两端本身就对称的部分砍掉,作为 \(A\) 和 \(E\) 的部分,然后中间找一个回文串进行扩展

会出现一下两种情况
那么找相同串的情况可以翻转一次接在最后做一遍 \(KMP\),由于中间插入了一个特殊字符,\(KMP\) 后不会跨边界
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e7+5;
char c[maxn],a[maxn],b[maxn];
int n,cnt1,tot,len,cnt,p[maxn],ans,nxt[maxn],mx[maxn];
void manacher(){
memset(p,0,sizeof p);
for(int t=1,mid=0,r=0;t<=cnt;t++){
if(t<=r)p[t]=min(p[mid*2-t],r-t+1);
while(a[t+p[t]]==a[t-p[t]])p[t]++;
if(t+p[t]>r)r=p[t]+t-1,mid=t;
}
return ;
}
void init(){
for(int i=1;i<=len/2;i++){
if(c[i]==c[len-i+1])tot++;
else break;
}
n=len-tot*2;
for(int i=1;i<=n;i++){
c[i]=c[i+tot];
}
return ;
}
void pre(){
a[0]='?';
a[cnt=1]='#';
for(int i=1;i<=n;i++){
a[++cnt]=c[i];
a[++cnt]='#';
}
}
void kmp(){
memset(nxt,0,sizeof nxt);
memset(mx,0,sizeof mx);
for(int i=cnt1-1,j=0;i>=1;i--){
while(j&&b[i]!=b[cnt1-j])j=nxt[j];
if(b[i]==b[cnt1-j])j++;
nxt[i]=j;
}
for(int i=n;i>=1;i--){
mx[i]=max(mx[i+1],nxt[i]);
}
return ;
}
void pre1(){
cnt1=n;
for(int i=1;i<=n;i++)b[i]=c[i];
b[++cnt1]='$';
for(int i=n;i>=1;i--){
b[++cnt1]=c[i];
}
return ;
}
void solve(){
for(int i=1;i<=cnt;i++){
int posl=(i-p[i])/2;
int posr=(i+p[i])/2;
if(nxt[posr]<=posl)ans=max(ans,p[i]-1+nxt[posr]*2);
if(mx[posr]>=posl)ans=max(ans,p[i]-1+posl*2);
}
return ;
}
void work(){
pre();
manacher();
pre1();
kmp();
solve();
return ;
}
int main(){
scanf("%s",c+1);
len=strlen(c+1);
init();
if(tot==n/2){
cout<<n;
return 0;
}
work();
reverse(c+1,c+n+1);
work();
cout<<ans+tot*2;
return 0;
}
noip模拟42的更多相关文章
- Noip模拟42 2021.8.17
T1 卷 一看跟没有上司的舞会一样,直接敲了然后试个自己造的样例对了就跑了... 然而把它想简单了,乘积取模,还能比大小吗????? 显然不能 所以直接让对数的加和跟着$dp$直接一起跑,比大小的都用 ...
- [考试总结]noip模拟42
开始给了一个简单的题目,但我还是没有珍惜. 一个简简单单的树形 \(dp\),然而因为取模却不知道该如何比较大小.. 其实可以取 \(log\),然后我就梦中惊坐起,然后想到了魔法少女lbw 淦 然后 ...
- NOIP模拟 1
NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. # 用 户 名 ...
- NOIP模拟17.9.22
NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥
- NOIP 模拟4 T2
本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
随机推荐
- js中变量提升和函数提升
变量提升和函数提升的总结 我们在学习JavaScript时,会遇到变量提升和函数提升的问题,为了理清这个问题,现做总结如下,希望对初学者能有所帮助 我们都知道 var 声明的变量有变量提升,而 let ...
- Adobe ColdFusion 反序列化漏洞(CVE-2017-3066)
影响版本 以下版本受到影响:Adobe ColdFusion (2016 release) Update 3及之前的版本,ColdFusion 11 Update 11及之前的版本,ColdFusio ...
- [源码解析] 机器学习参数服务器ps-lite 之(3) ----- 代理人Customer
[源码解析] 机器学习参数服务器ps-lite 之(3) ----- 代理人Customer 目录 [源码解析] 机器学习参数服务器ps-lite 之(3) ----- 代理人Customer 0x0 ...
- 「GM_脚本」获取 GitHub 项目文件的 jsDelivr CDN 地址「好像没啥用系列」
基本信息: name:「 GitHub 」获取文件的 jsDelivr 地址 desc:获取项目文件的 CDN 地址 url: https://github.com/wdssmq/userscript ...
- synchronized优化手段:锁膨胀、锁消除、锁粗化和自适应自旋锁...
synchronized 在 JDK 1.5 时性能是比较低的,然而在后续的版本中经过各种优化迭代,它的性能也得到了前所未有的提升,上一篇中我们谈到了锁膨胀对 synchronized 性能的提升,然 ...
- [TensorFlow2.0]-正则化
本人人工智能初学者,现在在学习TensorFlow2.0,对一些学习内容做一下笔记.笔记中,有些内容理解可能较为肤浅.有偏差等,各位在阅读时如有发现问题,请评论或者邮箱(右侧边栏有邮箱地址)提醒. 若 ...
- 用Matlab求解微分方程
用Matlab求解微分方程 解微分方程有两种解,一种是解析解,一种是数值解,这两种分别对应不同的解法 解析解 利用dsolve函数进行求解 syms x; s = dsolve('eq1,eq2,.. ...
- 一张图说明 iaas paas saas的区别
图片来源:https://www.bilibili.com/video/BV1QJ411S7c4 P2 云服务的三种模式 1laaS(基础设施即服务) laas(Infrastructure as ...
- The Apache Tomcat Native library which allows using OpenSSL was not found on the java.library.path 问题解决记录
1.问题 启动Tomcat之后,在浏览器输入IP后显示503,查看catalina.log发现报错: 2.问题定位:缺少 tomcat-native library 就是说 缺少Tomcat Nati ...
- Apache Druid 远程代码执行 CVE-2021-25646 漏洞复现
Apache Druid 远程代码执行 CVE-2021-25646 漏洞复现 前言 Apache Druid 是用Java编写的面向列的开源分布式数据存储,旨在快速获取大量事件数据,并在数据之上提供 ...