T1、02表示法

竟然有出题人敢出高精度(其实只是一个把string转成01串),开场看出记搜后十分犹豫到底要不要写高精,徘徊很久还是写了个小高精。

码(
/*
GGrun
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mk make_pair
#define ps push_back
#define fi first
#define se second
const int N=2e6+10,inf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f,mod=1e9+7;
inline ll read(){
char c=getchar();ll x=0,f=1;
while(!isdigit(c))f=c=='-'?-1:1,c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
string f[1010];
bool vis[1010];
inline string sol(int man){
if(vis[man])return f[man];
vis[man]=1;
for(int i=20;i>=0;--i){
if((man>>i)&1){
if(i==0)f[man]+="2(0)+";
else if(i==1)f[man]+="2+";
else f[man]=f[man]+"2("+sol(i)+")+";
}
}
f[man].pop_back();
return f[man];
}
string ans,s;
inline void chu(string &s){
int len=s.size();
for(int i=0;i<len;++i){
if((s[i]-'0')&1)s[i+1]+=10,s[i]--;
s[i]=((s[i]-'0')>>1)+'0';
}
if(s[0]=='0')s.erase(s.begin());
}
bool dan[N];
signed main(){
// #ifndef ONLINE_JUDGE
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);
// #endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
vis[1]=vis[2]=1;f[1]="2(0)",f[2]="2";
cin>>s;
int len=0;
while(s.size()){
if((s[s.size()-1]-'0')&1)dan[len]=1,--s[s.size()-1];
chu(s);
++len;
// cout<<s<<endl;
}
for(int i=len-1;i>=0;--i){
if(dan[i]){
if(i==0)ans+="2(0)+";
else if(i==1)ans+="2+";
else ans=ans+"2("+sol(i)+")+";
}
}
ans.pop_back();
cout<<ans;
}

T2、子串的子串

典型的扫描线,套路转化成pre,直接哈希用unordered_map记一下就行。

然后发现其实不行!!!!!!!!!

卡了半天,没想到怎么处理哈希冲突,后来T3给了点启发(只不过启发的不是正解),想到枚举的字符串每次只差一个字符,于是就可以用trie树去记他们的pre。

然后就炸空间了!

后来硬生生卡到了90分,空间还是开不下。

好吧,说说正解,其实注意到大部分字符串的长度不一样,长度也是他们本身的key值,可以用来减少哈希冲突,所以还是用unordered_map,每次枚举长度相同的字符串,然后就可以了。

码(
/*
GGrun
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mk make_pair
#define ps push_back
#define fi first
#define se second
const int N=2e6+10,inf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f,B=123;
inline ll read(){
char c=getchar();ll x=0,f=1;
while(!isdigit(c))f=c=='-'?-1:1,c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,q;
char s[5000];
ull hs[5000],ci[5000];
unordered_map<ull,int > pre;
inline ull hx(int l,int r){
return (hs[r]-hs[l-1]*ci[r-l+1]);
}
int c[3005];
inline void add(int x,int y){while(x<=n)c[x]+=y,x+=x&-x;}
inline int ask(int x){int ans=0;while(x)ans+=c[x],x^=x&-x;return ans;}
struct jj{
int l,r,id;
inline bool operator <(const jj&x)const{return l<x.l;}
}Q[N];
struct xian{
int l,v;
};
vector<xian> sao[3005];
int ans[N];
signed main(){
// #ifndef ONLINE_JUDGE
freopen("substring.in","r",stdin);
freopen("substring.out","w",stdout);
// #endif
// double ti=clock();
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
n=read(),q=read();
scanf("%s",s);
ci[0]=1;
for(int i=0;i<n;++i){
hs[i+1]=(hs[i]*B+s[i]);
ci[i+1]=ci[i]*B;
}
for(int i=1;i<=q;++i){
Q[i].l=read(),Q[i].r=read(),Q[i].id=i;
}
sort(Q+1,Q+1+q);
for(int len=1;len<=n;++len){
pre.clear();
for(int i=1,j=i+len-1;j<=n;++j,++i){
ull man=hx(i,j);
sao[i+1].ps({j,-1});sao[pre[man]+1].ps({j,1}),pre[man]=i;
}
}
for(int i=0,j=1;i<=n;++i){
for(auto k:sao[i]){
add(k.l,k.v);
}
while(j<=q&&Q[j].l==i)
ans[Q[j].id]=ask(Q[j].r),++j;
}
for(int i=1;i<=q;++i)
cout<<ans[i]<<'\n';
}

听说还可以用SAM做,不会,run了。

T3、魔法咒语

肯定得用trie树,先正着插一遍,能却确定不同的前缀有多少个,倒着插一遍能确定不同的后缀有多少个。把他们乘起来,再加上长度唯一的字符串(不重)的个数就是可能的方案数。

但是还要去重,怎么去呢,一个字符串会被不同前后缀组成多次,说明中间有一些字符即可以从前缀的来,也可以从后缀得来。所以对于一个字符,如果他既在前缀trie树中出现过,又在后缀trie树中出现过,那么这个字符便有了到底应该在前面出现还是应该在后面出现的选择,去重便要减一。

但是还有规定,前后两个字符串不能为空,那么对于两颗trie树来说,在第一层(根的儿子们)是必选的,他们不能计数。除去这些点后,每种小写字母在两棵树中的出现次数分别是 $ cnt1_i , cnt2_i $

那么最后答案再减去 $ \sum_{i ∈ 小写字母 }{cnt1_i * cnt2_i} $ 即可。

码(
/*
GGrun
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mk make_pair
#define ps push_back
#define fi first
#define se second
const int N=2e6+10,inf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f,mod=1e9+7;
inline ll read(){
char c=getchar();ll x=0,f=1;
while(!isdigit(c))f=c=='-'?-1:1,c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,cnt,son[10001*40][26],num1[26],num2[26];
string s[10001];
bool f[10001*40],dan[26];
inline void ins(string &s){
int now=0,len=s.size();
for(int i=0;i<len;++i){
if(!son[now][s[i]-'a'])son[now][s[i]-'a']=++cnt;
f[now]=1;
now=son[now][s[i]-'a'];
}
}
inline void sol(int num[],int now){
for(int i=0;i<26;++i)
if(son[now][i])num[i]+=now!=0,sol(num,son[now][i]);
}
signed main(){
// #ifndef ONLINE_JUDGE
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
// #endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
cin>>s[i],ins(s[i]);
ll ans=0,cnt1=cnt;
sol(num1,0);
for(int i=0;i<=cnt;++i){
for(int j=0;j<26;++j)
son[i][j]=0;
}
cnt=0;
for(int i=1;i<=n;++i){
// cout<<s[i].size()<<endl;
if(s[i].size()==1&&!dan[s[i][0]-'a'])++ans,dan[s[i][0]-'a']=1;
reverse(s[i].begin(), s[i].end()),ins(s[i]);
}
sol(num2,0);
ans+=cnt1*cnt;
for(int i=0;i<26;++i)
ans-=(ll)num1[i]*num2[i];
cout<<ans; }

T4、表达式

用线段树维护函数答案。

但是还得用CRT,好吧其实数论那块我根本没学明白。场上骗了30分,写的分块,忘了写线段树更优了,痛失10分。

简单复习(贺)了一下

码(
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mk make_pair
#define ps push_back
#define fi first
#define se second
const int N=1e6+10,inf=0x3f3f3f3f,B=sqrt(1e9);
const ll linf=0x3f3f3f3f3f3f3f3f;
inline ll read(){
char c=getchar_unlocked();ll x=0,f=1;
while(!isdigit(c))f=c=='-'?-1:1,c=getchar_unlocked();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar_unlocked();
return x*f;
}
int n,m,p,X[N],mod,t;
char op[N];
int ans[800005][8][30],ny[8],cntmod,mo[30];
inline ll qpow(ll x,ll y,ll mod){
ll ans=1;
while(y){
if(y&1)ans=ans*x%mod;
x=x*x%mod;y>>=1;
}
return ans;
}
inline void ad(int k,int pos){
if(op[pos]=='+'){
for(int i=1;i<=cntmod;++i){
ll mod=mo[i];
for(int j=0;j<mod;++j)
ans[k][i][j]=(j+X[pos])%mod;
}
}
else if(op[pos]=='*'){
for(int i=1;i<=cntmod;++i){
ll mod=mo[i];
for(int j=0;j<mod;++j)
ans[k][i][j]=((ll)j*X[pos])%mod;
}
}
else{
for(int i=1;i<=cntmod;++i){
ll mod=mo[i];
for(int j=0;j<mod;++j)
ans[k][i][j]=qpow(j,X[pos],mod);
}
}
}
inline void jian(int k,int l,int r){
if(l==r){
ad(k,l);
return;
}
int mid=l+r>>1;
jian(k<<1,l,mid),jian(k<<1|1,mid+1,r);
for(int i=1;i<=cntmod;++i){
ll mod=mo[i];
for(int j=0;j<mod;++j)
ans[k][i][j]=ans[k<<1|1][i][ans[k<<1][i][j]];
} }
inline void add(int k,int l,int r,int pos){
if(l==r){
ad(k,l);
return;
}
int mid=l+r>>1;
pos<=mid?add(k<<1,l,mid,pos):add(k<<1|1,mid+1,r,pos);
for(int i=1;i<=cntmod;++i){
ll mod=mo[i];
for(int j=0;j<mod;++j)
ans[k][i][j]=ans[k<<1|1][i][ans[k<<1][i][j]];
}
}
signed main(){ freopen("expr.in","r",stdin);
freopen("expr.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
t=read();
n=read(),m=read(),mod=read();
for(int i=1;i<=n;++i){
scanf(" %c",&op[i]);X[i]=read();
}
if(t<=3){
for(int i=1,opp,pos,x;i<=m;++i){
opp=read();
if(opp==1){
x=read()%mod;
for(int j=1;j<=n;++j){
if(op[j]=='+')x=(x+X[j])%mod;
else if(op[j]=='*')x=(ll)x*X[j]%mod;
else x=qpow(x,X[j],mod);
}
cout<<x<<'\n';
}
else pos=read(),op[pos]=getchar_unlocked(),X[pos]=read();
}
}
else{
ll p=mod;
for(int i=2;i*i<=mod;++i){
if(p%i==0){
ll op=1;
while(p%i==0)op=op*i,p/=i;
mo[++cntmod]=op;
for(int j=1,man=mod/op;j<op;++j)
if((ll)man*j%op==1){ny[cntmod]=j;break;}
}
}
if(p>1){
mo[++cntmod]=p;
for(int j=1,man=mod/p;j<p;++j)
if((ll)man*j%p==1){ny[cntmod]=j;break;}
}
jian(1,1,n);
for(int i=1,opp,pos,x;i<=m;++i){
opp=read();
if(opp==1){
x=read();
ll op=0;
for(int j=1;j<=cntmod;++j){
op=(op+(ll)mod/mo[j]*ny[j]%mod*ans[1][j][x%mo[j]]%mod)%mod;
}
cout<<op<<'\n';
}
else{
pos=read();op[pos]=getchar_unlocked();X[pos]=read();
add(1,1,n,pos);
}
}
}
}

总结

这场题主要是T2学了个unordered_map如何更优秀的避免哈希冲突,那就是多运用它们本身自带的key值。

T4其实感觉线段树部分会了,但不知道下次还会不会用CRT了。

P
其实我没有图片(

多校A层冲刺NOIP2024模拟赛04的更多相关文章

  1. 多校B层冲刺NOIP20211111模拟12

    题面:PDFhttp://xn--gwt928b.accoders.com/pdf/10248/10248.pdfhttp://xn--gwt928b.accoders.com/pdf/10248/1 ...

  2. 【CJOJ P1957】【NOIP2010冲刺十模拟赛】数字积木

    [NOIP2010冲刺十模拟赛]数字积木 Description 小明有一款新式积木,每个积木上都有一个数,一天小明突发奇想,要是把所有的积木排成一排,所形成的数目最大是多少呢? 你的任务就是读入n个 ...

  3. 冲刺Noip2017模拟赛7 解题报告——五十岚芒果酱

    1.二叉树(binary) .二叉树 (binary.cpp/c/pas) [问题描述] 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: ()若左子树不空,则左子树上所有结点的值均小于它的根结 ...

  4. 冲刺Noip2017模拟赛8 解题报告——五十岚芒果酱

    1.鼎纹 [问题描述] 据说鼎纹的 种制造 式是 铜模印出来的,这是我国古代劳动 智慧 的结晶.铜模印过的地 ,会留下深深的印记,经过时间的炼化,洗 练成历史的遗存. 聪明的古代劳动人民拥有一个 a ...

  5. 冲刺Noip2017模拟赛4 解题报告——五十岚芒果酱

    题1 韬韬抢苹果(apple) [问题描述] 又到了收获的季节,树上结了许多韬韬,错了,是许多苹果,有很多个小韬韬都来摘苹 果.每个韬韬都想要最大的苹果,所以发生了争执,为了解决他们的矛盾,出题人定了 ...

  6. 冲刺Noip2017模拟赛2 解题报告——五十岚芒果酱

    题1 牛跑步(running) [题目描述] 新牛到部队,CG 要求它们每天早上搞晨跑,从 A 农场跑到 B 农场.从 A 农场到 B 农场中有 n- 个路口,分别标上号,A 农场为 号,B 农场为 ...

  7. 冲刺Noip2017模拟赛1 解题报告——五十岚芒果酱

    题1 国际象棋(chess) [问题描述] 有N个人要参加国际象棋比赛,该比赛要进行K场对弈.每个人最多参加2场对弈,最少参加0场对弈.每个人都有一个与其他人都不相同的等级(用一个正整数来表示).在对 ...

  8. 冲刺Noip2017模拟赛6 解题报告——五十岚芒果酱

    1.ksum(ksum) [问题描述] Peter喜欢玩数组.NOIP这天,他从Jason手里得到了大小为n的一个正整数 数组. Peter求出了这个数组的所有子段和,并将这n(n+)/2个数降序排序 ...

  9. 冲刺Noip2017模拟赛5 解题报告——五十岚芒果酱

    1. 公约数(gcd) [问题描述] 给定一个正整数,在[,n]的范围内,求出有多少个无序数对(a,b)满足 gcd(a,b)=a xor b. [输入格式] 输入共一行,一个正整数n. [输出格式] ...

  10. 冲刺Noip2017模拟赛3 解题报告——五十岚芒果酱

    题1  素数 [问题描述] 给定一个正整数N,询问1到N中有多少个素数. [输入格式]primenum.in 一个正整数N. [输出格式]primenum.out 一个数Ans,表示1到N中有多少个素 ...

随机推荐

  1. 全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类

    全网最适合入门的面向对象编程教程:30 Python 的内置数据类型-object 根类 摘要: 在 Python 中,所有的类都直接或间接继承自一个根类,这个根类是Object.Object类是 P ...

  2. 神奇的发现——所有的aarch64架构的CPU平台下的深度学习框架均不原生支持CUDA

    一个记录: 神奇的发型--所有的aarch64架构的CPU平台下的深度学习框架均不原生支持CUDA 不论是mindspore.pytorch.TensorFlow框架只要是aarch64架构的CPU下 ...

  3. 纪念IE浏览器退役,哈哈哈!!!

    网址: https://haokan.baidu.com/v?pd=wisenatural&vid=16024148879625055169 ========================= ...

  4. 记录一次实验室linux系统的GPU服务器死机排查过程——某显卡满负荷导致内核进程超时导致系统死机

    在自己没有管理多台高负荷的ubuntu显卡服务器之前,我是万万想不到linux服务器居然也是如此容易死机的. 什么每个版本的TensorFlow调用显卡驱动时和内核不兼容,什么系统自动升级导致的显卡驱 ...

  5. 【CMake系列】11-CMake Pack

    cmake pack 用于将我们的写好的项目 打包,发送给使用方:打包后产生的内容有 源代码包 二进制包 平台原生的二进制安装 Debian -> .deb red hat -> .rpm ...

  6. TwinCAT3 - 实现自己的Dictionary

    目录 1,前言 2,C#的字典 3,TwinCAT3的字典 定义功能块 添加方法 4,用起来 1,前言 C#有字典,TwinCAT没字典,咋办,自己写一个咯 2,C#的字典 C#的字典使用很简单,下面 ...

  7. 【Mac + Python + Selenium】之获取验证码图片code并进行登录

    自己新总结了一篇文章,对代码进行了优化,另外附加了静态图片提取文字方法,两篇文章可以结合着看:<[Python]Selenium自动化测试之动态识别验证码图片方法(附静态图片文字获取)> ...

  8. java 知识

    1. 单文件java 例子和简单项目例子 http://kleinfelter.com/java-hello-world-with-visual-studio-code-and-eclipse jav ...

  9. C++17: 用折叠表达式实现一个IsAllTrue函数

    前言 让我们实现一个 IsAllTrue 函数,支持变长参数,可传入多个表达式,必须全部计算为true,该函数才返回true. 本文记录了逐步实现与优化该函数的思维链,用到了以下现代C++新特性知识, ...

  10. Mongodb入门1

    学如逆水行舟不进则退 | 心似平原走马易放难追 MongoDB是一个NOSQL类型的数据库,关于SQL与NOSQL的区别不是本文的重点,不在此进行记录. MongoDB安装 然后再将MongoDB的安 ...