多校A层冲刺NOIP2024模拟赛04
多校A层冲刺NOIP2024模拟赛04
学校OJ赛时 rank28,T1 0pts,T2 100pts,T3 20pts,T4 25pts
accoders rank15,T1 100pts,T2 100pts,T3 20pts,T4 25pts
不是,也没人告诉我两个OJ文件名不一样啊
02表示法
递归 + 高精除低精。
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); FILE *ErrFile=errfile("err.err"); #else FILE *Infile = infile("power.in"),*OutFile = outfile("power.out"); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; const int N = 200; string s; ll n; inline int divide(string &s){ if(!s.size()) return -1; if(s.size() == 1 && s[0] == '0') return -1; if(s.size() == 1 && s[0] == '1'){ s = "";return 1; } int res = (s.back() - '0')%2;s.back() -= res; int n = s.size(),x = 0; string sh;bool flag = false; rep(i,0,n-1,1){ x = x*10 + (s[i] - '0'); if(x >= 2) sh.push_back(x/2+'0'),x %= 2,flag = true; else if(flag) sh.push_back('0'); } s = sh; return res; } #define pii pair<int,int> #define mk make_pair void work(string s){ if(s == "0") return cout<<0,void(); if(s == "1") return cout<<"1",void(); if(s == "2") return cout<<"2",void(); if(!s.size()) return; vector<pii> p; rep(i,0,999999,1){ int x = divide(s); if(x == -1) break; if(!x) continue; p.emplace_back(mk(i,1)); } reverse(p.begin(),p.end()); int len = p.size(); for(int i = 0;i < len; ++i){ if(p[i].first == 1) {cout<<2;goto ed;} cout<<2; if(p[i].first != 1) cout<<'('; work(to_string(p[i].first)); if(p[i].first != 1) cout<<')'; ed:; if(i != len - 1) cout<<'+'; } } inline void solve(){ cin>>s; work(s); } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
子串的子串
赛时写了一个
就是把每次查询的串截出来,然后跑个后缀数组求
求后缀数组用的倍增法,用
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = infile("substring.in"),*OutFile = outfile("substring.out"); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; const int N = 3010; char *p1,*p2,buf[1<<23]; #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++) #ifdef linux #define pc putchar_unlocked #else #define pc putchar #endif namespace IO{ template<typename T>inline bool read(T &x){x=0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x<<1)+(x<<3)+(s^48);if(!f) x=~x+1;return true;} inline bool read(double &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;} inline bool read(long double &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;} inline bool read(float &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;} inline bool read(string &str){string ().swap(str);char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false; for(;s!=' '&&s!='\n'&&s!=EOF;s=gc())str.push_back(s);return true;} inline bool read_line(string &str){string ().swap(str);char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false;for(;s!='\n'&&s!=EOF;s=gc()){str.push_back(s);}return true;} inline bool read_line(char *str){int len=0;char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false;for(;s!='\n'&&s!=EOF;s=gc()){str[len]=s;len++;}str[len]='\0';return true;} inline bool read(char &s){char x=gc();for(;x==' '||x=='\n';x=gc());if(x==EOF||x==' '||x=='\n')return false;s=x;return true;} inline bool read(char *s){int len=0;char x=gc();for(;x==' '||x=='\n';x=gc());if(x==EOF)return false;for(;x!=' '&&x!='\n'&&x!=EOF;x=gc())s[len++]=x;s[len]='\0';return true;} template<class T,class... Args> inline bool read(T &x,Args&... args){return (read(x)&&read(args...));} template<class T>inline void write(T x){static T st[45];int top=0;if(x<0)x=~x+1,pc('-');do{st[top++]=x%10;}while(x/=10);while(top)pc(st[--top]^48);} inline void write(char x){pc(x);} inline void write(string s){for(int i=0;s[i];++i) pc(s[i]);} inline void write(char *s){int len=strlen(s);for(int i=0;i<len;++i) pc(s[i]);} inline void write(const char *s){int len=strlen(s);for(int i=0;i<len;++i) pc(s[i]);} template<class T,class... Args> inline void write(T x,Args... args){write(x);write(args...);} }using namespace IO; int n,m,sa[N],rk[N],tp[N],ht[N],ct[N];char s[N],s1[N]; inline void Qsort(int m){ rep(i,1,m,1) ct[i] = 0; rep(i,1,n,1) ++ct[rk[i]]; rep(i,2,m,1) ct[i] += ct[i-1]; drep(i,n,1,1) sa[ct[rk[tp[i]]]--] = tp[i]; } inline bool cmp(int x,int y,int w){return (tp[x]==tp[y]&&tp[x+w]==tp[y+w]);} inline void get_sa(){ n = strlen(s+1); int m = 27; rep(i,1,n,1) rk[i] = s[i] - 'a' + 1,tp[i] = i; Qsort(m); for(int w=1,p=0;w<=n;m=p,p=0,w<<=1){ rep(i,n-w+1,n,1) tp[++p]=i; rep(i,1,n,1) if(sa[i]>w) tp[++p]=sa[i]-w; Qsort(m); rep(i,1,n,1) swap(tp[i],rk[i]); p=rk[sa[1]]=1; rep(i,2,n,1) rk[sa[i]]=cmp(sa[i-1],sa[i],w)?p:++p; if(p==n) break; } int k = 0; rep(i,1,n,1){ if(!rk[i]) continue; if(k) --k; while(s[i+k] == s[sa[rk[i]-1]+k]) k++; ht[rk[i]] = k; } } inline void solve(){ read(n,m);read(s1+1); while(m--){ int l,r;ll ans;read(l,r); rep(i,l,r,1) s[i-l+1] = s1[i]; n = r-l+1; s[n+1] = '\0'; get_sa(); ans = 1ll*n*(n+1)/2; rep(i,2,n,1) ans -= ht[i]; rep(i,1,n,1) ht[i] = rk[i] = sa[i] = tp[i] = 0; write(ans,'\n'); } } signed main(){ solve(); }
正解是预处理,二维前缀和。
记
先枚举子串长度,再枚举左端点,通过预处理的前缀和求出这
点
之间该串都有贡献,那么应该将上一次出现的左端点
即
,回答询问
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = infile("substring.in"),*OutFile = outfile("substring.out"); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; const int N = 3010; char s[N]; int n,m,ans[N][N]; ull hs[N],pw[N],base = 131; inline ull get_hash(int l,int r){return hs[r] - hs[l-1]*pw[r-l+1];} inline void solve(){ cin>>n>>m>>(s+1); pw[0] = 1;rep(i,1,n,1) pw[i] = pw[i - 1] * base; rep(i,1,n,1) hs[i] = hs[i-1]*base + s[i]; rep(len,1,n,1){ __gnu_pbds::gp_hash_table<ull,int> mp; rep(l,1,n-len+1,1){ int r = l + len - 1; ull h = get_hash(l,r); ans[mp[h]][r]--; mp[h] = l; } } drep(l,n,1,1) rep(r,l,n,1) ans[l][r] += ans[l + 1][r] + ans[l][r - 1] - ans[l+1][r-1] + 1; while(m--){ int l,r;cin>>l>>r;cout<<ans[l][r]<<'\n'; } } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
魔法咒语
考虑一个串是被两个拼起来的或者就一个,一个的特判掉。
考虑对于每一个前缀扩展,假设拓展的第一个字符为
加入
反之,那么就考虑所有第一个字符为
前缀的话插入一个正向的Trie就可以,看后缀的话插入一个后缀的Trie即可。
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = infile("magic.in"),*OutFile = outfile("magic.out"); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; const int N = 4e5 + 10; struct Trie{ int tree[N][27],cnt[N],tot; inline void insert(string s,bool rev){ int p = 0,len = s.size()-1; if(rev) reverse(s.begin(),s.end()); rep(i,0,len,1){ int x = s[i] - 'a' + 1; if(!tree[p][x]) tree[p][x] = ++tot,cnt[x] += rev; p = tree[p][x]; } } }t1,t2; ll ans = 0,n; string s[N]; bitset<27> ok,flag; inline void solve(){ cin>>n; rep(i,1,n,1){ cin>>s[i]; t1.insert(s[i],false);t2.insert(s[i],true); int len = s[i].size(); ok[s[i].back() - 'a' + 1] = true; if(len == 1 && !flag[s[i][0] - 'a' + 1]) ans++,flag[s[i][0] - 'a' + 1] = true; } rep(i,1,t1.tot,1) rep(j,1,26,1) if(!t1.tree[i][j]) ans += t2.cnt[j]; else if(ok[j]) ans++; cout<<ans<<'\n'; } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
表达式
线段树。不太懂啊。
将给的模数分解成
至于以
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = infile("expr.in"),*OutFile = outfile("expr.out"); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #define fi first #define se second #define pii pair<char,int> #define mk make_pair const int N = 2e5 + 10; int n,m,mod; pii a[N]; struct Segment_Tree{ struct segment_tree{ int l,r,val[30]; #define l(k) tree[k].l #define r(k) tree[k].r #define val(k) tree[k].val }tree[N<<2]; int p; unordered_map<char,function<int(int,int)> > op = { {'+',[&](int a,int b){return (a+b)%p;}}, {'*',[&](int a,int b){return 1ll*a*b%p;}}, {'^',[&](int a,int b){int res = 1;for(;b;b >>= 1,a = 1ll*a*a%p) if(b&1) res = 1ll*res*a%p;return res;}} }; inline void pushup(int k){ rep(i,0,p-1,1) val(k)[i] = val(k<<1|1)[val(k<<1)[i]]; } void build(int k,int l = 1,int r = n){ l(k) = l,r(k) = r; if(l == r){ rep(i,0,p-1,1) val(k)[i] = op[a[l].fi](i,a[l].se); return; } int mid = (l + r) >> 1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); pushup(k); } void change(int k,int pos){ if(l(k) == r(k)){ rep(i,0,p-1,1) val(k)[i] = op[a[pos].fi](i,a[pos].se); return; } int mid = (l(k) + r(k)) >> 1; if(pos <= mid) change(k<<1,pos);else change(k<<1|1,pos); pushup(k); } }T[4]; int exgcd(int a,int b,int &x,int &y){ if(!b) return x = 1,y = 0,a; int d = exgcd(b,a%b,x,y); int t = x;x = y;y = t - (a/b)*y; return d; } namespace TP{ const int N = 2e5 + 10; char op[N]; int testid,n,m,mod,a[N]; inline int power(int a,int b,int mod){ int res = 1; for(;b;b>>=1,a = 1ll*a*a%mod) if(b&1) res = 1ll*res*a%mod; return res; } inline void solve(){ cin>>n>>m>>mod; rep(i,1,n,1) cin>>op[i]>>a[i]; while(m--){ int p,x;cin>>p; if(p == 1){ cin>>x; rep(i,1,n,1){ if(op[i] == '+') x = (0ll+x+a[i])%mod; if(op[i] == '*') x = 1ll*x*a[i]%mod; if(op[i] == '^') x = power(x,a[i],mod); } cout<<x<<'\n'; } else{ char c;int y; cin>>x>>c>>y;op[x] = c,a[x] = y; } } } } inline void solve(){ int id; cin>>id; if(id <= 3){ TP::solve(); return; } cin>>n>>m>>mod; rep(i,1,n,1) cin>>a[i].fi>>a[i].se; vector<int> d; int res = mod; for(int i = 2;i * i <= res; ++i){ if(res % i == 0){ int k = 1; while(res % i == 0) res /= i,k *= i; d.emplace_back(k); } } if(res > 1) d.emplace_back(res); for(int i = 0;i < d.size(); ++i){ T[i].p = d[i],T[i].build(1); } // exit(0); auto get_ans = [&](vector<int> &v){ int res = 0; for(int i = 0;i < v.size(); ++i){ int m = mod/d[i],b,y; exgcd(m,d[i],b,y); res = (res + 1ll * v[i] * m % mod * b % mod) % mod; } return (res + mod) % mod; }; while(m--){ int op;cin>>op; if(op == 1){ int x;cin>>x; vector<int> v; for(int i = 0;i < d.size(); ++i) v.emplace_back(T[i].tree[1].val[x%T[i].p]); cout<<get_ans(v)<<'\n'; } else{ int x,z;cin>>x;char y;cin>>y>>z; a[x] = mk(y,z); for(int i = 0;i < d.size();T[i++].change(1,x)); } } } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18454912
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】