Solved:11/12
Penalty:1059
Rank:1/146(N+2)
Dirt:48%
Problem | A | B | C | D | E | F | G | H | I | J | K | L | 題數 | 罰時 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Time | 11 | 2 | 214 | 127 | 107 | 61 | 28 | 39 | 84 | 159 | 16 | 11 | 1059 | |
dirt | 3 | 1 | 1 | 3 | 2 |
A,B,G,H,L:簽到
F
直接扔一個帶修莫隊板子上去就過了。雖然1000的值域應該有點說法。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MN=2e5+5;
struct QUE{int l,r,t,id,typ,ans;}q[MN];
struct UPD{int fr,to,x;}u[MN];
int N,M,T,a[MN],pos[MN],totq,totu;
int ans;
inline bool cmp(const QUE&o,const QUE&oo)
{return (pos[o.l]^pos[oo.l])?(pos[o.l]<pos[oo.l]):((pos[o.r]^pos[oo.r])?(pos[o.r]<pos[oo.r]):(o.t<oo.t));}
int num[1000005];
inline bool cmp2(const QUE&o,const QUE&oo){return o.id<oo.id;}
int main()
{
cin>>N>>M;
T=1357;
for(int i=1;i<=N;++i) cin>>a[i],pos[i]=(i-1)/T+1;
for(int i=1;i<=M;++i)
{
int op;
cin>>op;
if(op==1||op==2)
{
++totq;
cin>>q[totq].l>>q[totq].r;
q[totq].id=totq;
q[totq].typ=op;
q[totq].t=totu;
}
else
{
++totu;
cin>>u[totu].x;
cin>>u[totu].to;
u[totu].fr=a[u[totu].x];
a[u[totu].x]=u[totu].to;
}
}
for(int i=totu;i;--i) a[u[i].x]=u[i].fr;
std::sort(q+1,q+totq+1,cmp);
register int i=1,j=0,l=1,r=0,ans=0;
for(i=1;i<=totq;++i)
{
for(;l>q[i].l;--l) ans+=((num[a[l-1]]^=1)?1:-1);
for(;l<q[i].l;++l) ans+=((num[a[l]]^=1)?1:-1);
for(;r<q[i].r;++r) ans+=((num[a[r+1]]^=1)?1:-1);
for(;r>q[i].r;--r) ans+=((num[a[r]]^=1)?1:-1);
for(;j<q[i].t;++j)
{
a[u[j+1].x]=u[j+1].to;
if(u[j+1].x<=q[i].r&&u[j+1].x>=q[i].l)
ans+=((num[u[j+1].fr]^=1)?1:-1),ans+=((num[u[j+1].to]^=1)?1:-1);
}
for(;j>q[i].t;--j)
{
a[u[j].x]=u[j].fr;
if(u[j].x<=q[i].r&&u[j].x>=q[i].l)
ans+=((num[u[j].fr]^=1)?1:-1),ans+=((num[u[j].to]^=1)?1:-1);
}
q[i].ans=q[i].typ==1?(ans==0||ans==1000):ans;
}
std::sort(q+1,q+totq+1,cmp2);
for(i=1;i<=totq;++i) printf("%d\n",q[i].ans);
}
I
結論:當且僅當\(a\)是\(b\)的原根(特判\(b=2\))。
證明:考慮模b剩餘系下的操作,則加b操作相當於沒有,因此想取到所有的數必須要a的冪次遍歷1到b-1,必要性得證。充分性考慮透過一系列操作得到若干\(k_rb+r(r=1,2,\dots,b-1)\),那隻需要把這些數加充分多個b就能讓它們變成連續段,後面的數就只要不斷加b就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6;
bool vis[N];
int main(){
int a,b;
cin>>a>>b;
a%=b;
if(a==1){
if(b<=2)cout<<"YES\n";
else cout<<"NO\n";
return 0;
}
vis[0]=vis[1]=1;
ll r=a;
while(!vis[r]){
vis[r]=1;
r=r*a%b;
}
bool fl=1;
for(int i=0;i<b;++i)
if(!vis[i]){fl=0;break;}
cout<<(fl?"YES":"NO")<<'\n';
}
E
模擬題,寫得清楚點就行。
set會T(垃圾pta)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int m,c[2],o;
int mx[2][2],mn[2][2];
ll w[2][2];
string op[4]={"EF","EFX","EF1","E"};
int check(int x,int y){
if(w[x][x]>=w[x][y])return 0;
if(w[x][x]>=w[x][y]-mn[x][y])return 1;
if(w[x][x]>=w[x][y]-mx[x][y])return 2;
return 3;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>m;
mn[0][0]=mn[0][1]=mn[1][0]=mn[1][1]=2e9;
for(int i=1;i<=m;++i){
cin>>c[0]>>c[1]>>o;
mx[0][o]=max(mx[0][o],c[0]);
mn[0][o]=min(mn[0][o],c[0]);
mx[1][o]=max(mx[1][o],c[1]);
mn[1][o]=min(mn[1][o],c[1]);
w[0][o]+=c[0];
w[1][o]+=c[1];
cout<<op[max(check(0,1),check(1,0))]<<'\n';
}
}
D
分層圖最短路。建\(\log w\)層,第k層表示加速k次的圖。加速的點連向下一層的同一個點,壞路直接連回第0層。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,int> pll;
const int N=2e4*21+5;
int id(int x,int i){return (x-1)*21+i;}
vector<pii> e[N];
void adde(int x,int y,int z){
e[x].push_back(pii(y,z));
}
int n,m,S,T,x,y,z,p;
string ch;
ll dis[N];
bool vis[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>S>>T;
for(int i=1;i<=m;++i){
string ch;
cin>>x>>y>>z>>ch;
if(ch=="G"){
for(int j=0;j<=20;++j)adde(id(x,j),id(y,j),(z+(1<<j)-1)>>j);
}
else{
for(int j=0;j<=20;++j)adde(id(x,j),id(y,0),(z+(1<<j)-1)>>j);
}
}
cin>>p;
for(int i=1;i<=p;++i){
cin>>x>>z;
for(int j=0;j<20;++j)adde(id(x,j),id(x,j+1),z);
}
priority_queue<pll,vector<pll>,greater<pll>> pq;
memset(dis,63,sizeof(dis));
dis[id(S,0)]=0;
pq.push(pll(0,id(S,0)));
while(!pq.empty()){
int u=pq.top().second;
pq.pop();
if(vis[u])continue;
vis[u]=1;
for(auto [v,w]:e[u]){
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
pq.push(pll(dis[v],v));
}
}
}
ll ans=1e18;
for(int i=0;i<=20;++i)ans=min(ans,dis[id(T,i)]);
if(ans>1e16)cout<<"-1\n";
else cout<<ans<<'\n';
}
J
dp+容斥。暴力列舉約數更新即可。
\[f_i=\sum_{d\neq 1, d|a_i}-\mu(d)g_{d,i}, g_{d,i} = g_{d,i-1}+f_i[d|i]
\]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9+7;
bool np[N];
int pri[N],cnt,mu[N];
void sieve(int n){
for(int i=2;i<=n;++i){
if(!np[i])pri[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*pri[j]<=n;++j){
np[i*pri[j]]=1;
if(!(i%pri[j]))break;
mu[i*pri[j]]=-mu[i];
}
}
}
int n,x;
ll f[N],g[N];
int main(){
sieve(1e5);
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
f[1]=1;
for(int i=1;i<=n;++i){
cin>>x;
for(int j=1;j*j<=x;++j)if(!(x%j)){
f[i]=(f[i]-mu[j]*g[j])%mod;
if(j*j<x)f[i]=(f[i]-mu[x/j]*g[x/j])%mod;
}
for(int j=1;j*j<=x;++j)if(!(x%j)){
g[j]=(g[j]+f[i])%mod;
if(j*j<x)g[x/j]=(g[x/j]+f[i])%mod;
}
}
cout<<(f[n]%mod+mod)%mod<<'\n';
}
C
你們出字串都喜歡板子套板子嗎.jpg
對所有串的正串和反串分別建一棵trie,把結束節點的二元組記下來。
對每個詢問,相當於查詢x[i]在a在T1中的節點子樹、y[i]在b在T2中的節點子樹的二元組數量。
DFS序轉一下,就變成靜態矩陣求和了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,MN=1e6+5;
string rev(string s){
int len=s.length();
for(int i=0;i<len-i-1;++i)swap(s[i],s[len-i-1]);
return s;
}
int n,m;
struct trie{
int tot,c[MN][26],val[MN],dfn[MN],nfd[MN],id,sz[MN];
trie(){tot=1,id=0;}
int insert(string s){
int u=1;
for(char ch:s){
int o=ch-'a';
if(!c[u][o])c[u][o]=++tot;
u=c[u][o];
}
return u;
}
void dfs(int u){
dfn[u]=++id,nfd[id]=u,sz[u]=1;
for(int i=0;i<26;++i)if(c[u][i])dfs(c[u][i]),sz[u]+=sz[c[u][i]];
}
int find(string s){
int u=1;
for(int ch:s){
int o=ch-'a';
if(!c[u][o])return 0;
u=c[u][o];
}
return u;
}
}T[2];
int pos[MN],tim[MN];
int cnt=0;
struct QUE{
int id,x,y,typ;
bool operator<(const QUE& q)const{
return x<q.x;
}
}q[N*2];
int ans[N];
int c[MN];
void upd(int x,int y){
for(;x<=T[1].tot;x+=x&-x)c[x]+=y;
}
int qry(int x){
int r=0;
for(;x;x-=x&-x)r+=c[x];
return r;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;++i){
string s;
cin>>s;
int u=T[0].insert(s);
int v=T[1].insert(rev(s));
pos[u]=v,++tim[u];
}
T[0].dfs(1);
T[1].dfs(1);
for(int i=1;i<=m;++i){
string s,t;
cin>>s>>t;
int u=T[0].find(s),v=T[1].find(rev(t));
if(u&&v){
q[++cnt]=(QUE){i,T[0].dfn[u]-1,v,-1};
q[++cnt]=(QUE){i,T[0].dfn[u]+T[0].sz[u]-1,v,1};
}
}
sort(q+1,q+cnt+1);
for(int i=1,j=1;i<=T[0].tot;++i){
if(pos[T[0].nfd[i]])upd(T[1].dfn[pos[T[0].nfd[i]]],tim[T[0].nfd[i]]);
while(q[j].x==i){
ans[q[j].id]+=q[j].typ*(qry(T[1].dfn[q[j].y]+T[1].sz[q[j].y]-1)-qry(T[1].dfn[q[j].y]-1));
++j;
}
}
for(int i=1;i<=m;++i)cout<<ans[i]<<'\n';
}