说句闲话
学了会儿头插dp,转移是这样写的,\(Chen\_jr\)锐评:插头你还短路,你不烧谁烧
于是脑子烧坏了来补题解
(!is_d) && (!is_r) && mp[i+1][j] & mp[i][j+1]// need to make a new component
&& ( H.Push( u+ts[j-1]+2*ts[j],val ),0 );
(!is_d) && (is_r)
&& ( ( mp[i+1][j] && (H.Push(u,val),0) )//down
|| ( mp[i][j+1] && (H.Push(u-is_r*ts[j-1]+is_r*ts[j],val ),0) ) );//right
(is_d) && (!is_r)
&& ( ( mp[i][j+1] && (H.Push(u,val),0) )//right
|| ( mp[i+1][j] && (H.Push(u-is_d*ts[j]+is_d*ts[j-1],val ),0) ) );//down
(is_d==1 && is_r==2)
&& ( H.Push( u-2*ts[j-1]-ts[j],val ),0 );
(is_r==1 && is_d==2 ) && ( i == Edx && j == Edy)
&& (ans+=val);
A.装备
水题,成对给出先考虑建边,发现是一对内向树森林,有环的一定废,否则翻转一个位置即将它到跟的边方向全翻转,可以无脑上LCT,只需要Makeroot
和Access
,从高位到低位贪心翻即可,要注意不能在低位影响高位的结果,除非高位翻与不翻的权值一样
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i)
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;
const int maxn=2e5+10;
vector<int>Ans;
map<pii,int>Map;
int n,m,Lim;
int w[maxn];
int a[maxn],b[maxn],rk[maxn];
struct LCT_tree{
#define lch V[p].son[0]
#define rch V[p].son[1]
#define Son(p) (p==V[V[p].fa].son[1])
#define Isroot(p) (V[V[p].fa].son[0]!=p && V[V[p].fa].son[1]!=p)
struct Vertex{int son[2],siz,val,maxi,fa,lazy;}V[maxn];
int tot;
int New(int fa){ ++tot;V[tot].siz=1;V[tot].fa=fa;return tot; }
void Pushup(int p){ V[p].siz=V[lch].siz+V[rch].siz+1;V[p].maxi=max({ V[lch].maxi,V[rch].maxi,V[p].val }); }
void Pushdown(int p){
if(!V[p].lazy)return;
swap(V[lch].son[0],V[lch].son[1]); swap(V[rch].son[0],V[rch].son[1]);
V[lch].lazy^=1,V[rch].lazy^=1,V[p].lazy^=1;
}
void Spread(int p){ if(!Isroot(p))Spread(V[p].fa); Pushdown(p); }
void Rotate(int p){
int f=V[p].fa,lf=V[f].fa,s=Son(p),ls=Son(f);
if(!Isroot(f))V[lf].son[ls]=p;
V[p].fa=lf;
V[f].son[s]=V[p].son[s^1]; V[V[p].son[s^1]].fa=f;
V[p].son[s^1]=f,V[f].fa=p;
Pushup(f),Pushup(p);
}
void Splay(int p){
Spread(p);
for(int f=V[p].fa;!Isroot(p);Rotate(p),f=V[p].fa)
if(!Isroot(f))Rotate(Son(f)==Son(p) ? f : p);
}
int Access(int x){ int p; for(p=0;x;p=x,x=V[x].fa) Splay(x),V[x].son[1]=p,Pushup(x); return p; }
void Makeroot(int p){ p=Access(p);swap(V[p].son[0],V[p].son[1]); V[p].lazy^=1; }
int Findroot(int p){ Access(p);Splay(p);Pushdown(p);while(lch)p=lch,Pushdown(p); Splay(p);return p; }
vector<int>vec;
void Flat(int p){ if(!p)return;Flat(lch);vec.emplace_back(p);Flat(rch); }
void Refresh(int p){ if(!p)return;Refresh(lch),Refresh(rch);Pushup(p); }
void Work(int x,int Tim){
Access(x);Splay(x);
if(V[x].siz-1>Lim || V[x].maxi>Tim)return;
//assert(V[x].siz>1 && V[x].maxi>0);
Lim-=(V[x].siz-1);
vec.resize(0);Flat(x);
for(int i=0;i+1<vec.size();++i){
int u=rk[vec[i]],v=rk[vec[i+1]],id=Map[pii(v,u)];
Ans.emplace_back(id);//assert(id);
swap(a[id],b[id]);
Map.erase(pii(v,u));Map[pii(u,v)]=id;
V[vec[i]].val=(w[u]==w[v] ? 0 : id);
}
V[x].val=0;
Refresh(x);Makeroot(x);
}
}T;
int tot,siz[maxn];
struct Graph{
struct eg{ int from,to,next; }e[maxn];
int len,head[maxn];int deg[maxn];
void lqx(int from,int to)
{ e[++len].from=from,e[len].to=to,e[len].next=head[from],head[from]=len;++deg[to]; }
int dfn[maxn],low[maxn],st[maxn],top,bel[maxn],Te;bool vis[maxn];
void Tarjan(int u){
dfn[u]=low[u]=++Te;st[++top]=u;vis[u]=true;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v])Tarjan(v),low[u]=min(low[u],low[v]);
else if(vis[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
++tot;
while(st[top+1]!=u){
++siz[tot];
bel[st[top]]=tot;
vis[st[top--]]=false;
}
}
}
void Build(){
queue<int>q;
Rep(i,1,tot)if(!deg[i] && siz[i]==1)q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=true;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
T.V[v].fa=u;q.push(v);
T.V[v].val=(w[rk[v]]==w[rk[u]] ? 0 : Map[pii(rk[v],rk[u])]);
}
}
Rep(i,1,tot)if(!deg[i] && siz[i]==1)T.Makeroot(i);
}
}G,F;
void Work(int x,int Tim){
if(!F.vis[G.bel[x]])return;
T.Work(G.bel[x],Tim);
}
void solve(){
cin>>n>>m>>Lim;Rep(i,1,n)cin>>w[i],T.New(0);
Rep(i,1,m){ cin>>a[i]>>b[i];Map[pii(a[i],b[i])]=i;G.lqx(a[i],b[i]); }
Rep(i,1,n)if(!G.dfn[i])G.Tarjan(i);
Rep(i,1,n)if(siz[G.bel[i]]==1)rk[G.bel[i]]=i;
Rep(i,1,G.len){
int u=G.bel[G.e[i].from],v=G.bel[G.e[i].to];
if(u==v)continue;
F.lqx(v,u);
}F.Build();
Dwn(i,m,1)if(w[a[i]]<w[b[i]])Work(a[i],i);
cout<<Ans.size()<<"\n";
for(auto it : Ans)cout<<it<<"\n";
}
int main (){
fre(equipment);
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0;
}
B.比赛
看完数据范围套路设\(f_{l,r,k}\),表示区间\([l,r]\)最后\(k\)胜出的概率,这样从\(k\)将区间一分为二,左右互不影响,变成子问题,发现子问题的\(k\)一定为左右边界其一,于是简化状态\(f_{l,r,0/1/2}\),表示左边界出线,右边界出线,左右都出线,转移即可。发现不太会算概率,于是直接考虑计数方案数。可以理解为,钦定若干比赛结果,计数满足这些比赛结果的比赛顺序的方案数,乘上达到钦定结果的概率,再除以比赛顺序的总数,即为其概率。
tmd又被n=1坑了
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i)
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;
const int maxn=5e2+10,Mod=998244353,inv2=(Mod+1)>>1;
int pw(int x,int p){int res=1,base=x;while(p){if(p&1)res=1LL*res*base%Mod;base=1LL*base*base%Mod;p>>=1;}return res;}
int Inv(int x){return pw(x,Mod-2);}
int fac[maxn],ifac[maxn],inv[maxn];
int n,a[maxn];
int dp[maxn][maxn][3],vis[maxn][maxn][3];
int C[maxn][maxn],P[maxn][maxn];
int Sol(int l,int r,int k){
if(vis[l][r][k])return dp[l][r][k];
vis[l][r][k]=true;
if(l==r)return dp[l][r][k]=1;
if(l+1==r && k==2)return dp[l][r][k]=1;
if(k==0){
int res=0;
Rep(i,l+1,r){
int val1=Sol(l,i,2),val2=Sol(i,r,0);
res=(res+1LL*val1*val2%Mod*P[l][i]%Mod*C[r-l-1][r-i])%Mod;
}
return dp[l][r][k]=res;
}
if(k==1){
int res=0;
Dwn(i,r-1,l){
int val1=Sol(l,i,1),val2=Sol(i,r,2);
res=(res+1LL*val1*val2%Mod*P[r][i]%Mod*C[r-l-1][i-l])%Mod;
}
return dp[l][r][k]=res;
}
if(k==2){
int res=0;
Rep(i,l+1,r-1){
int val1=Sol(l,i,2),val2=Sol(i,r,2),tmp=1LL*val1*val2%Mod*C[r-l-2][i-l-1]%Mod;
res=(res+1LL*tmp*P[l][i])%Mod;
res=(res+1LL*tmp*P[r][i])%Mod;
}
return dp[l][r][k]=res;
}
//assert(k>=0 && k<=2);
//return dp[l][r][k]=0;
return 0;
}
void solve(){
cin>>n;Rep(i,1,n)cin>>a[i];
fac[0]=ifac[0]=1;Rep(i,1,n)fac[i]=1LL*fac[i-1]*i%Mod;
ifac[n]=Inv(fac[n]);Dwn(i,n-1,1)ifac[i]=1LL*ifac[i+1]*(i+1)%Mod;
C[0][0]=1;Rep(i,1,n){ C[i][0]=1;Rep(j,1,i)C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod; }
Rep(i,1,n)Rep(j,1,n)P[i][j]=1LL*a[i]*Inv(a[i]+a[j])%Mod;
// cerr<<Sol(1,2,1)<<"\n";
cout<<1LL*Sol(1,n,0)*ifac[n-1]%Mod<<"\n";
Rep(i,2,n-1)
cout<<1LL*Sol(1,i,1)*Sol(i,n,0)%Mod*ifac[n-1]%Mod*C[n-1][i-1]%Mod<<"\n";
if(n!=1)cout<<1LL*Sol(1,n,1)*ifac[n-1]%Mod<<"\n";
}
int main (){ fre(tournament);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }
C.取石子游戏
不会证SG,打表也看不出来,题解说啥我干啥
点击查看代码
// ubsan: undefined
// accoders
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i)
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;
const int maxn=280000+10,Mod=998244353,Inv2=(Mod+1)>>1;
int n,m;
int Add(int x,int y){ return (x+y)>m ? x+y-m-1 : x+y; }
int Ckadd(int x,int y){ return (x+y)>=Mod ? x+y-Mod : x+y; }
int Cksub(int x,int y){ return x-y<0 ? x-y+Mod : x-y; }
struct Ver{
int f[21];
int &operator[](const int &i){ return f[i]; }
int operator[](const int &i)const{ return f[i]; }
void Clear(){ memset(f,0,sizeof(f)); }
friend Ver operator + (const Ver &A,const Ver &B){
static Ver res;
Rep(i,0,m)res[i]=Ckadd(A[i],B[i]);
return res;
}
friend Ver operator - (const Ver &A,const Ver &B){
static Ver res;
Rep(i,0,m)res[i]=Cksub(A[i],B[i]);
return res;
}
friend Ver operator * (const Ver &A,const Ver &B){
static Ver res;res.Clear();
Rep(i,0,m)Rep(j,0,m)res[Add(i,j)]=(res[Add(i,j)]+1LL*A[i]*B[j])%Mod;
return res;
}
friend Ver operator * (const Ver &A,const int &x){
static Ver res;
Rep(i,0,m)res[i]=1LL*A[i]*x%Mod;
return res;
}
}F[21][maxn],tmp[maxn];
int V=1<<17;
void FWT_XOR(Ver f[],int opt){
if(opt==-1)opt=Inv2;
for(int m=1;m<V;m<<=1)for(int i=0;i<V;i+=(m<<1))for(int j=0;j<m;++j)
{Ver x=f[i+j],y=f[i+j+m];f[i+j]=(x+y)*opt,f[i+j+m]=(x-y)*opt;}
}
int G[maxn],H[maxn];
void FWT(int f[],int opt){
if(opt==-1)opt=Inv2;
for(int m=1;m<V;m<<=1)for(int i=0;i<V;i+=(m<<1))for(int j=0;j<m;++j)
{int x=f[i+j],y=f[i+j+m];f[i+j]=1LL*(x+y)*opt%Mod,f[i+j+m]=1LL*(x-y)*opt%Mod;}
}
int cnt[maxn];
void solve(){
cin>>n>>m;
V=1<<(__lg((100000/(m+1)))+1);
Rep(i,1,n)++F[i][0][0],FWT_XOR(F[i],1);
Rep(t,1,n){
int len,c,x;cin>>len>>c;++cnt[c];
for(int i=0;i<V;++i)tmp[i].Clear();
Rep(i,1,len){ cin>>x; ++tmp[x/(m+1)][x%(m+1)]; }
FWT_XOR(tmp,1);
for(int i=0;i<V;++i)F[c][i]=F[c][i]*tmp[i];
}
Rep(i,1,n)FWT_XOR(F[i],-1);
V=1<<18;
G[0]=1;FWT(G,1);
Rep(c,1,n)if(cnt[c]){
cerr<<c<<"\n";
for(int i=0;i<V;++i)H[i]=0;
for(int i=0;i<=V/(m+1);++i)Rep(j,0,m)
H[i*(m+1)+j]=(H[i*(m+1)+j]+F[c][i][j])%Mod;
bool fg=true;
for(int i=0;i<V;++i)fg&=(!H[i]);
assert(!fg);
FWT(H,1);
for(int i=0;i<V;++i)G[i]=1LL*G[i]*H[i]%Mod;
}
FWT(G,-1);
int ans=0;for(int i=1;i<V;++i)ans=(ans+G[i])%Mod;
cout<<(ans+Mod)%Mod;
}
int main (){ fre(nim);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }