21杭電多校第二場
A
簽到題,對於一個正方體,有\(8\)種頂點均在正方體頂點上滿足條件的正三角形
顯然\(Ans=\sum\limits_{i=1}^{n-1}8i^3=8(\frac{n(n-1)}{2})^2=2(n-1)n\)
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 100100 #define MOD 1000000007 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-b+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } ll n,inv2; ll qp(ll x,ll t,ll res=1) { for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res; } int main() { inv2=qp(2,MOD-2);ll ans;rep(T,1,read()) { n=read()%MOD;n=mns(n,1);ans=mul(n,n+1); ans=mul(ans,ans);ans=mul(ans,2);printf("%d\n",ans); } }
B
樹鏈剖分維護二次函式,每次新增都是新增一段二次函式
平移後變成\(ax^2+bx+c\)的形式,其中\(x\)為線段樹的橫座標,這樣\(a,b,c\)可加,能直接維護
每次單點查詢得到答案
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 100100 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-b+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline 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-'0';ch=getchar();} return x*f; } int n,nxt[MAXN<<1],fst[MAXN],to[MAXN<<1],cnt,val[MAXN]; int sz[MAXN],dep[MAXN],fa[MAXN],hvs[MAXN],bl[MAXN],in[MAXN],tot; void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} void dfs(int x,int pa) { sz[x]=1,fa[x]=pa; ren if(to[i]^pa) { dep[to[i]]=dep[x]+1;dfs(to[i],x); sz[x]+=sz[to[i]],hvs[x]=sz[to[i]]>sz[hvs[x]]?to[i]:hvs[x]; } } void Dfs(int x,int anc) { bl[x]=anc,in[x]=++tot;if(!hvs[x]) return ;Dfs(hvs[x],anc); ren if(to[i]^fa[x]&&to[i]^hvs[x]) Dfs(to[i],to[i]); } ll taga[MAXN<<2],tagb[MAXN<<2],tagc[MAXN<<2]; void build(int k,int l,int r) { taga[k]=tagb[k]=tagc[k]=0;if(l==r) return ; int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r); } void pshd(int k) { taga[k<<1]+=taga[k],taga[k<<1|1]+=taga[k]; tagb[k<<1]+=tagb[k],tagb[k<<1|1]+=tagb[k]; tagc[k<<1]+=tagc[k],tagc[k<<1|1]+=tagc[k]; taga[k]=tagb[k]=tagc[k]=0LL; } void mdf(int k,int l,int r,int a,int b,ll A,ll B,ll C) { if(a<=l&&r<=b) {taga[k]+=A,tagb[k]+=B,tagc[k]+=C;return ;} int mid=l+r>>1;if(taga[k]!=0||tagb[k]!=0||tagc[k]!=0) pshd(k); if(a<=mid) mdf(k<<1,l,mid,a,b,A,B,C); if(b>mid) mdf(k<<1|1,mid+1,r,a,b,A,B,C); } ll query(int k,int l,int r,int x) { if(l==r) return taga[k]*x*x+tagb[k]*x+tagc[k];int mid=l+r>>1; if(taga[k]!=0||tagb[k]!=0||tagc[k]!=0) pshd(k); return x<=mid?query(k<<1,l,mid,x):query(k<<1|1,mid+1,r,x); } inline int lca(int a,int b) { for(;bl[a]!=bl[b];a=fa[bl[a]]) if(dep[bl[a]]<dep[bl[b]]) swap(a,b); if(in[a]>in[b]) swap(a,b);return a; } inline ll sqr(ll x){return x*x;} void work(int a,int b) { int z=lca(a,b),l=0,r=0,tmp=dep[a]+dep[b]-2*dep[z]+1; mdf(1,1,n,in[z],in[z],0,0,sqr(dep[a]-dep[z]+1)); for(;bl[a]!=bl[z];a=fa[bl[a]]) { l=r+1,r+=dep[a]-dep[bl[a]]+1; mdf(1,1,n,in[bl[a]],in[a],1,-2LL*(in[a]+l),sqr(in[a]+l)); } l=r+1,r+=dep[a]-dep[z]; if(in[a]>in[z]) mdf(1,1,n,in[z]+1,in[a],1,-2LL*(in[a]+l),sqr(in[a]+l)); l=tmp+1; for(;bl[b]!=bl[z];b=fa[bl[b]]) { r=l-1,l-=dep[b]-dep[bl[b]]+1; mdf(1,1,n,in[bl[b]],in[b],1,2LL*(r-in[b]),sqr(in[b]-r)); } r=l-1,l-=dep[b]-dep[z]; if(in[b]>in[z]) mdf(1,1,n,in[z]+1,in[b],1,2LL*(r-in[b]),sqr(in[b]-r)); } inline ll solve(int a){return query(1,1,n,in[a]);} int main() { n=read();int a,b,c; rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a); int q=read();dfs(1,0);Dfs(1,1); build(1,1,n); while(q--) { c=read(),a=read();if(c&1) b=read(); if(c&1) work(a,b);else printf("%lld\n",solve(a)); } }
C
先處理出從\(z\)出發的最短路,若\(dis_x\neq dis_y\)則顯然勝負已分
對於\(dis_x=dis_y\)的情況,若均不能到達則為平局
否則設\(f[x][y][k]\)表示\(Alice\)在\(x\)點,\(Bob\)在\(y\)點,現在該誰走的勝負情況
\(DP\)即可,二者均只會選擇對自己最優的後繼狀態,這個轉移只會沿著最短路邊轉移,狀態很少
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 100100 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-b+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline 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-'0';ch=getchar();} return x*f; } int n,m,f[1010][1010][2],dis[1010],q[1010],hd,tl,z; vector<int> G[1010],H[1010];vector<pii> del; int dp(int x,int y,int k) { if(!k&&(x==z||y==z)) { if(x==z&&y==z) return 2; else return x==z?1:3; } if(f[x][y][k]) return f[x][y][k]; if(!k) { f[x][y][k]=3;for(auto i:H[x]) if(i!=y||i==z) f[x][y][k]=min(f[x][y][k],dp(i,y,k^1)); } else { f[x][y][k]=1;for(auto i:H[y]) if(i!=x||i==z) f[x][y][k]=max(f[x][y][k],dp(x,i,k^1)); } del.pb({x,y});return f[x][y][k]; } int main() { int x,y,t,a,b;rep(T,1,read()) { n=read(),m=read(),x=read(),y=read(),z=read(); rep(i,1,n) dis[i]=inf,G[i].clear(); rep(i,1,m) a=read(),b=read(),G[a].pb(b),G[b].pb(a); q[hd=tl=1]=z,dis[z]=0; while(hd<=tl) { t=q[hd++];for(auto v:G[t]) if(dis[v]==inf) dis[v]=dis[t]+1,q[++tl]=v; } if(dis[x]!=dis[y]) {puts(dis[x]<dis[y]?"1":"3");continue;} if(dis[x]==inf) {puts("2");continue;} rep(i,1,n) H[i].clear(); rep(i,1,n) for(auto v:G[i]) if(dis[v]==dis[i]+1) H[v].pb(i); printf("%d\n",dp(x,y,0));for(auto x:del) f[x.fi][x.se][0]=f[x.fi][x.se][1]=0; } }
D
對於每個查詢先不考慮異或的限制,相當於求有多少個\(i\)滿足\(l\le i\le r\)且\(las_i< l\)
令每個點座標為\((las_i,i)\),可以用掃描線樹狀陣列解決
而對於異或的限制,在\(trie\)樹上查詢,可以得到一些節點,只有經過這些節點的值對於這次查詢才有意義
因此我們可以把詢問放到每個\(trie\)樹的節點上,插入值時同樣把這個點的座標加入經過的所有節點
這樣對於\(trie\)樹的所有節點都掃描線二位數點就可以解決問題
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
int n,m,g[MAXN],c[MAXN],ans[MAXN],res;
int tr[MAXN*18][2],tot,las[MAXN],pos[MAXN];
void mdf(int x,int w){for(;x<=n;x+=x&-x) c[x]+=w;}
int query(int x,int res=0){for(;x;x-=x&-x) res+=c[x];return res;}
struct node{int l,r,x,id;};
bool operator < (node &a,node &b)
{
if(a.x!=b.x) return a.x<b.x;
if(a.r!=b.r) return a.r<b.r;
return a.id<b.id;
}
vector<node> vec[MAXN*18];
inline void ins(int x,int id)
{
int p=0,t;dwn(i,17,0)
{
t=(x>>i)&1;if(!tr[p][t]) tr[p][t]=++tot;
p=tr[p][t];vec[p].pb({0,id,las[id],0});
}
}
inline void insq(int l,int r,int a,int b,int id)
{
int t,res=0,p=0,g;
dwn(i,17,0)
{
t=(a>>i)&1,g=(b>>i)&1;
if(g)
{
if(tr[p][t]) {vec[tr[p][t]].pb({l,r,l-1,id});}
if(tr[p][t^1]) p=tr[p][1^t];
else {p=-1;break;}
}
else
{
if(tr[p][t]) p=tr[p][t];
else {p=-1;break;}
}
}
if(~p) vec[p].pb({l,r,l-1,id});
}
int main()
{
n=read();rep(i,1,n) g[i]=read(),pos[i]=-1;
rep(i,1,n) las[i]=pos[g[i]],pos[g[i]]=i;
rep(i,1,n) ins(g[i],i);
m=read();int l,r,a,b;
rep(i,1,m) {l=read(),r=read(),a=read(),b=read();insq(l,r,a,b,i);}
rep(i,1,tot)
{
sort(vec[i].begin(),vec[i].end());
for(auto x:vec[i])
if(!x.id) mdf(x.r,1);
else ans[x.id]+=query(x.r)-query(x.l-1);
for(auto x:vec[i]) if(!x.id) mdf(x.r,-1);
}
rep(i,1,m) printf("%d\n",ans[i]);
}
(賽時直接莫隊可過
E
簽到題,只有最前面連續若干個相同的\(k\)個相同字元可以有不同方案,答案為\(2^{k-1}\)
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
int n,ans;char s[MAXN];
int main()
{
rep(T,1,read())
{
n=read();scanf("%s",s+1);ans=1;
rep(i,2,n) if(s[i]==s[i-1]) ans=mul(ans,2);else break;
printf("%d\n",ans);
}
}
F
由於調和級數複雜度為\(nlogn\),因此對每個\(p\)可以分別計算
考慮\(FWT\)的過程,已知\(A[0],A[1],A[2]\);\(B[0],B[1],B[2]\)
由題目規定位運算的定義可知
\(C[0]=A[0]B[0]\)
\(C[2]=A[2]B[0]+A[0]B[2]+A[2]B[2]\\\quad \ \ \ =(A[0]+A[2])(B[0]+B[2])-A[0]B[0]\)
\(C[1]=A[0]B[1]+A[1]B[0]+A[1]B[1]+A[1]B[2]+A[2]B[1]\\\quad \ \ \ =(A[0]+A[1]+A[2])(B[0]+B[1]+B[2])-(A[0]+A[2])(B[0]+B[2])\)
則可令\(fwt\)過程為\(\{a_0,a_1,a_2\}\rightarrow\{a_0,a_0+a_1+a_2,a_0+a_2\}\)
令\(ifwt\)過程為\(\{a_0,a_1,a_2\}\rightarrow\{a_0,a_1-a_2,a_2-a_0\}\)
每次\(fwt\)後再按題意計算即可
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 600100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) ((a-(b))%MOD+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
int n,a[MAXN],b[MAXN],c[MAXN],ans,A[MAXN],B[MAXN];
void trans(int &a,int &b,int &c)
{
c=pls(c,a),b=pls(b,c);
}
void itrans(int &a,int &b,int &c)
{
b=mns(b,c),c=mns(c,a);
}
void fwt(int *a,int n,int t)
{
for(int i=1;i<n;i*=3) for(int j=0;j<n;j+=i*3) rep(k,0,i-1)
if(!t) trans(a[j+k],a[j+k+i],a[j+k+2*i]);
else itrans(a[j+k],a[j+k+i],a[j+k+2*i]);
}
void solve(int *a,int *b,int n)
{
fwt(a,n,0);fwt(b,n,0);
rep(i,0,n-1) a[i]=mul(a[i],b[i]);fwt(a,n,1);
}
int main()
{
n=read();
rep(i,1,n) scanf("%d",&a[i]);
rep(i,1,n) scanf("%d",&b[i]);
rep(i,1,n) scanf("%d",&c[i]);
rep(p,1,n)
{
int t=n/p,pw=1,lim=1;rep(i,1,t) A[i]=a[i],B[i]=b[i];
while(lim<=t) lim*=3;solve(A,B,lim);
rep(i,1,lim) pw=mul(pw,c[p]),ans=pls(ans,mul(pw,A[i]));
rep(i,1,lim) A[i]=B[i]=0;
}
printf("%d\n",ans);
}
G
很容易想到線段樹維護矩陣,樸素的想法是維護一個\(6\times 6\)的矩陣,但事實上並不需要
考慮二三操作,相當於對行向量\((a,b)\)進行矩陣乘一個矩陣,即乘以\(\begin{pmatrix}3&3\\2&-2\end{pmatrix}\)或\(\begin{pmatrix}0 &1\\1&0\end{pmatrix}\)
對於線段樹每個節點維護\(\sum a_i,\sum b_i,\sum a_i^2,\sum b_i^2,\sum a_ib_i,tag_a,tag_b,tag_m\),其中\(tag_a,tag_b\)表示加法標記,\(tag_m\)表示矩陣乘法的標記
對於加法維護的各項容易推出,考慮乘一個矩陣\(\begin{pmatrix}c&d\\e&f\end{pmatrix}\)的影響
\(\sum a_i\rightarrow c\sum a_i+e\sum b_i\),\(\sum b_i\rightarrow d\sum a_i+f\sum b_i\)
則\(\sum a_ib_i\rightarrow\sum (ca_i+eb_i)(da_i+fb_i)=cd\sum a_i^2+ef\sum b_i^2+(cf+ed)\sum a_ib_i\),由之前維護的值可以轉移得到;\(\sum a_i^2,\sum b_i^2\)同理
注意\(tag_a,tag_b\)同樣需要變動,優先進行矩陣的\(tag\)運算因此需要將原先存在的加法\(tag\)變為先矩乘之後的值
例如\(ca+eb+tag_a'=c(a+tag_a)+e(b+tag_b)\)即\(tag_a\rightarrow c\ tag_a+e\ tag_b\);\(tag_b\)同理
這樣每次\(pushdown\)的時候需要優先進行\(tag_m\)的運算再\(pushdown\)加法\(tag\)
查詢普通區間查詢\(\sum a_ib_i\)即可
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
int n,a[MAXN],b[MAXN];
inline void inc(ll &x,int y){x=pls(x,y);}
struct mat
{
int a[2][2];
mat(){a[0][0]=a[1][1]=1,a[0][1]=a[1][0]=0;}
mat operator *(const mat &x)
{
mat res;
rep(i,0,1) rep(j,0,1)
{
res.a[i][j]=0;rep(k,0,1)
res.a[i][j]=pls(res.a[i][j],mul(a[i][k],x.a[k][j]));
}
return res;
}
}exc,trans,one;
struct node{mat tagm;ll s[2],s2[2],tag[2],ans;}tr[MAXN<<2];
inline void upd(int k)
{
tr[k].ans=pls(tr[k<<1].ans,tr[k<<1|1].ans);
rep(i,0,1) tr[k].s[i]=pls(tr[k<<1].s[i],tr[k<<1|1].s[i]);
rep(i,0,1) tr[k].s2[i]=pls(tr[k<<1].s2[i],tr[k<<1|1].s2[i]);
}
inline ll sqr(ll x){return mul(x,x);}
void build(int k,int l,int r)
{
if(l==r)
{
tr[k].tag[0]=tr[k].tag[1]=0;
tr[k].s[0]=a[l],tr[k].s[1]=b[l];
tr[k].s2[0]=sqr(a[l]);tr[k].s2[1]=sqr(b[l]);
tr[k].ans=mul(a[l],b[l]);
return ;
}
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
upd(k);
}
inline void Add(int k,int l,int r,int t,int x)
{
if(!x) return ;inc(tr[k].tag[t],x);
inc(tr[k].s2[t],pls(mul(tr[k].s[t],2*x),mul(mul(x,x),r-l+1)));
inc(tr[k].ans,mul(x,tr[k].s[t^1]));
inc(tr[k].s[t],mul(r-l+1,x));
}
inline void Mdf(int k,int l,int r,mat m)
{
tr[k].tagm=tr[k].tagm*m;
int a=m.a[0][0],b=m.a[1][0],c=m.a[0][1],d=m.a[1][1],p,q,tmp;
p=tr[k].s2[0],q=tr[k].s2[1],tmp=tr[k].ans;
tr[k].ans=mul(tr[k].ans,pls(mul(a,d),mul(b,c)));
inc(tr[k].ans,pls(mul(mul(a,c),p),mul(mul(b,d),q)));
tr[k].s2[0]=pls(mul(p,sqr(a)),mul(q,sqr(b)));
inc(tr[k].s2[0],mul(mul(a,b),mul(tmp,2)));
tr[k].s2[1]=pls(mul(p,sqr(c)),mul(q,sqr(d)));
inc(tr[k].s2[1],mul(mul(c,d),mul(tmp,2)));
p=tr[k].s[0],q=tr[k].s[1];
tr[k].s[0]=pls(mul(a,p),mul(b,q));
tr[k].s[1]=pls(mul(c,p),mul(d,q));
p=tr[k].tag[0],q=tr[k].tag[1];
tr[k].tag[0]=pls(mul(a,p),mul(b,q));
tr[k].tag[1]=pls(mul(c,p),mul(d,q));
}
void pshd(int k,int l,int r,int mid)
{
Mdf(k<<1,l,mid,tr[k].tagm);Mdf(k<<1|1,mid+1,r,tr[k].tagm);
rep(i,0,1)
Add(k<<1,l,mid,i,tr[k].tag[i]),
Add(k<<1|1,mid+1,r,i,tr[k].tag[i]);
tr[k].tagm=one;rep(i,0,1) tr[k].tag[i]=0;
}
void add(int k,int l,int r,int a,int b,int t,int x)
{
if(a<=l&&r<=b) {Add(k,l,r,t,x);return ;}
int mid=l+r>>1;pshd(k,l,r,mid);
if(a<=mid) add(k<<1,l,mid,a,b,t,x);
if(b>mid) add(k<<1|1,mid+1,r,a,b,t,x);
upd(k);
}
void mdf(int k,int l,int r,int a,int b,mat x)
{
if(a<=l&&r<=b) {Mdf(k,l,r,x);return ;}
int mid=l+r>>1;pshd(k,l,r,mid);
if(a<=mid) mdf(k<<1,l,mid,a,b,x);
if(b>mid) mdf(k<<1|1,mid+1,r,a,b,x);
upd(k);
}
ll query(int k,int l,int r,int a,int b)
{
if(a<=l&&r<=b) return tr[k].ans;
int mid=l+r>>1;ll res=0;pshd(k,l,r,mid);
if(a<=mid) res=query(k<<1,l,mid,a,b);
if(b>mid) res=pls(query(k<<1|1,mid+1,r,a,b),res);
return res;
}
int main()
{
n=read();rep(i,1,n) a[i]=read(),b[i]=read();
exc.a[0][1]=exc.a[1][0]=1,exc.a[0][0]=exc.a[1][1]=0;
trans.a[0][0]=trans.a[0][1]=3,trans.a[1][0]=2,trans.a[1][1]=MOD-2;
one.a[0][0]=one.a[1][1]=1,one.a[0][1]=one.a[1][0]=0;
build(1,1,n);int l,r,x,t;
rep(Q,1,read())
{
t=read();
if(t==1) {t=read(),l=read(),r=read(),x=read();add(1,1,n,l,r,t,x);}
else
{
l=read(),r=read();
if(t==2) mdf(1,1,n,l,r,trans);
else if(t==3) mdf(1,1,n,l,r,exc);
else printf("%lld\n",query(1,1,n,l,r));
}
}
}
H
簡單\(dp\)組合
先\(dp\)出每門課\(i\)花費\(j\)時間最多可以獲得多少分
再設\(dp[i][j][k]\)表示前\(i\)門課花了\(j\)時間掛了\(k\)門課獲得的最大分數,用之前處理出的陣列轉移
最後對所有合法答案取\(max\)
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define w first
#define v second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
int n,m,p,f[55][550],dp[55][550][5],ans;
vector<pii> vec[55];
map<string,int> hsh;
int main()
{
rep(T,1,read())
{
n=read();string s;int a,b;
rep(i,1,n) {cin>>s;hsh[s]=i;}
m=read();rep(i,1,m) {cin>>s;a=read(),b=read();vec[hsh[s]].pb({a,b});}
m=read(),p=read();
rep(i,1,n) {f[i][0]=0;rep(j,1,m) f[i][j]=-inf/2;}
rep(i,1,n) for(auto x:vec[i])
dwn(j,m,x.v) f[i][j]=min(max(f[i][j],f[i][j-x.v]+x.w),100);
rep(i,0,n) rep(j,0,m) rep(k,0,p) dp[i][j][k]=-inf/2;
dp[0][0][0]=0;
rep(i,1,n) rep(j,0,m) rep(k,0,j) rep(t,0,p)
if(f[i][j-k]>=60) dp[i][j][t]=max(dp[i][j][t],dp[i-1][k][t]+f[i][j-k]);
else if(t) dp[i][j][t]=max(dp[i][j][t],dp[i-1][k][t-1]+f[i][j-k]);
ans=-1;rep(i,0,m) rep(j,0,p) ans=max(ans,dp[n][i][j]);
printf("%d\n",ans);hsh.clear();rep(i,1,n) vec[i].clear();
}
}
I
奇妙列舉 咕
J
可以發現,最終得到的數列一定是一個長度為\(P-1\)的排列
令這個排列為\(\pi\),排列中第\(i\)個數為\(\pi(i)\),排列的逆序對數為\(n(\pi)\),\(sgn(\pi)=(-1)^{n(\pi)}\)
\[sgn(\pi)=\frac{\prod_{0<i<j\le p-1}\pi(j)-\pi(i)}{\prod_{0<i<j\le p-1}j-i}=\prod_{0<i<j\le p-1} \frac{\pi(j)-\pi(i)}{j-i}=\prod_{0<i<j\le p-1}\frac{(ja)\%P-(ia)\%P}{j-i} \]想要消掉這個取模,考慮對\(sgn(\pi)\)取模,即:
\[\begin{aligned} sgn(\pi) &\equiv \prod_{0<i<j\le p-1}\frac{(ja)\%P-(ia)\%P}{j-i} (mod\ \ P)\\ sgn(\pi) &\equiv \prod_{0<i<j\le p-1}\frac{a\cdot (j-i)\%P}{j-i} (mod\ \ P)\\ sgn(\pi) &\equiv a^\frac{P(P-1)}{2} \prod_{0<i<j\le p-1}(j-i)\cdot inv(j-i)\ \ (mod\ \ P)\\ sgn(\pi) &\equiv a^\frac{P(P-1)}{2}\ \ (mod\ \ P)\\ \end{aligned} \]只需要用快速冪判斷\(a^\frac{P(P-1)}{2}\ \ (mod\ \ P)\)是否等於\(1\)即可
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) ((__int128)(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll a,MOD;
ll qp(ll x,ll t,ll res=1)
{
for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
return res;
}
int main()
{
rep(T,1,read())
{
a=read(),MOD=read();
puts((qp(a,(MOD-1)/2)==1LL)?"0":"1");
}
}
K
若\(i\&j=k\),則說明\(k\)的二進位制表示是\(i,j\)的子集,對於一個\(k\)需要考慮所有這樣的數
設\(f_i\)表示所有能轉移到\(i\)的\(a\)的最大值,則\(f_i=max\{a_j\},i\subseteq j\)
列舉所有顯然複雜度過高,可以每次只向減少\(1\)個\(1\)的數轉移即\(f_i=max\{f_j\},j=i|(1<<k)\),複雜度\(nlogn\)
又由於\(a,b\)存在負數,因此需要維護\(maxa,mina,maxb,minb\),最後的答案一定可以從這\(2\times2\)種情況中得到
對每個點再求一次後綴\(max\)即為所求
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 300100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
int n,mxa[MAXN],mxb[MAXN],mna[MAXN],mnb[MAXN],t=1;
ll ans[MAXN],res;
int main()
{
rep(T,1,read())
{
n=read();t=1;while((1<<t)<n) t++;
rep(i,0,n-1) {scanf("%d",&mxa[i]);mna[i]=mxa[i];}
rep(i,0,n-1) {scanf("%d",&mxb[i]);mnb[i]=mxb[i];}
dwn(i,n-1,0) rep(j,0,t) if((i>>j)&1)
mxa[i^(1<<j)]=max(mxa[i^(1<<j)],mxa[i]),
mxb[i^(1<<j)]=max(mxb[i^(1<<j)],mxb[i]),
mna[i^(1<<j)]=min(mna[i^(1<<j)],mna[i]),
mnb[i^(1<<j)]=min(mnb[i^(1<<j)],mnb[i]);
rep(i,0,n-1)
ans[i]=max(1LL*mxa[i]*mxb[i],1LL*mxa[i]*mnb[i]),
ans[i]=max(max(1LL*mna[i]*mxb[i],1LL*mna[i]*mnb[i]),ans[i]);
res=ans[n-1];
dwn(i,n-2,0) ans[i]=max(ans[i],ans[i+1]),res=pls(res,ans[i]);
printf("%d\n",(res+MOD)%MOD);
}
}
L
簽到題,暴力判斷即可
#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline 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-'0';ch=getchar();}
return x*f;
}
char s[100100];int n;
int cheq()
{
rep(i,1,n-5)
if(s[i]=='1'&&s[i+1]=='1'&&s[i+2]=='4'&&s[i+3]=='5'&&s[i+4]=='1'&&s[i+5]=='4')
return 1;
return 0;
}
int main()
{
rep(T,1,read())
{
scanf("%s",s+1);n=strlen(s+1);
puts(cheq()?"AAAAAA":"Abuchulaile");
}
}