2024“釘耙編程”中國大學生算法設計超級聯(lián)賽(4)
題面:
https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E9%9D%A2.pdf
題解:
https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E8%A7%A3.pdf
Code:
A. 超維攻堅
#include<cstdio>
const int N=15,inf=~0U>>1;
int Case,n,i,j,k,S,o;bool ok[(1<<N)+1];
struct P{
int x,y,z;
P(){}
P(int _x,int _y,int _z){x=_x,y=_y,z=_z;}
P operator-(const P&p)const{return P(x-p.x,y-p.y,z-p.z);}
P operator*(const P&p)const{return P(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);}
int operator^(const P&p)const{return x*p.x+y*p.y+z*p.z;}
}p[N];
inline int ptoplane(const P&a,const P&b,const P&c,const P&p){return((b-a)*(c-a))^(p-a);}
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
inline bool colinear(const P&a,const P&b,const P&p){
P t=(a-b)*(b-p);
return !t.x&&!t.y&&!t.z;
}
inline int sgn(int x){
if(x>0)return 1;
if(x<0)return -1;
return 0;
}
//12v^4
inline bool check(const P&a,const P&b,const P&c,const P&p){
return (((b-a)*(c-a))^((b-a)*(p-a)))>=0;
}
struct Face{
P a,b,c;
int sgn;
bool inside(const P&p)const{
return check(a,b,c,p)&&check(b,c,a,p)&&check(c,a,b,p);
}
}f[N*N*N];
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=0;i<n;i++)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
for(i=1;i<1<<n;i++)ok[i]=0;
for(S=1;S<1<<n;S++){
if(__builtin_popcount(S)<=1){
ok[S]=1;
continue;
}
int m=0;
bool same=1;
for(i=0;i<n;i++)if(S>>i&1)for(j=0;j<i;j++)if(S>>j&1)for(k=0;k<j;k++)if(S>>k&1){
if(colinear(p[i],p[j],p[k]))continue;
int l=inf,r=-inf;
for(o=0;o<n;o++)if(S>>o&1){
int tmp=ptoplane(p[i],p[j],p[k],p[o]);
umin(l,tmp);
umax(r,tmp);
}
if(l<0&&r>0)continue;
if(l||r)same=0;
f[m].a=p[i];
f[m].b=p[j];
f[m].c=p[k];
f[m].sgn=sgn(l)+sgn(r);
m++;
}
int mask=S;
if(!m){
//colinear
int xl=inf,xr=-inf;
int yl=inf,yr=-inf;
int zl=inf,zr=-inf;
int idl=n,idr=0;
for(i=0;i<n;i++)if(S>>i&1){
umin(xl,p[i].x);umax(xr,p[i].x);
umin(yl,p[i].y);umax(yr,p[i].y);
umin(zl,p[i].z);umax(zr,p[i].z);
umin(idl,i);umax(idr,i);
}
for(i=0;i<n;i++){
if(S>>i&1)continue;
if(!colinear(p[idl],p[idr],p[i]))continue;
if(p[i].x<xl||p[i].x>xr)continue;
if(p[i].y<yl||p[i].y>yr)continue;
if(p[i].z<zl||p[i].z>zr)continue;
mask|=1<<i;
}
}else if(same){
//just a face
for(i=0;i<n;i++){
if(S>>i&1)continue;
if(ptoplane(f[0].a,f[0].b,f[0].c,p[i]))continue;
for(j=0;j<m;j++)if(f[j].inside(p[i])){
mask|=1<<i;
break;
}
}
}else{
for(i=0;i<n;i++){
if(S>>i&1)continue;
for(j=0;j<m;j++){
int tmp=sgn(ptoplane(f[j].a,f[j].b,f[j].c,p[i]));
if(tmp&&tmp!=f[j].sgn)break;
}
if(j==m)mask|=1<<i;
}
}
ok[mask]=1;
}
int ans=0;
for(i=1;i<1<<n;i++)if(ok[i])ans++;
printf("%d\n",ans);
}
}
B. 黑白邊游戲
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
typedef unsigned int U;
typedef pair<U,U>P;
const int N=9,K=6,M=13055,CNT=305,inf=~0U>>1;
int a[CNT],b[CNT],f[CNT][M],perm[N],deg[N],d[N][N];bool g[N][N];U minS;
U two[N],w[N];P ident[N];
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
struct Info{
int n,m,tot,id[N][N],apsp[K][K][M];
map<U,int>T;
U mask[M];
vector<int>adj[M];
void init(int _n){
int i,j,k,o,A,B;
n=_n;
for(i=0;i<n;i++)for(j=0;j<i;j++)id[i][j]=id[j][i]=m++;
dfs(0);
for(i=1;i<=tot;i++){
sort(adj[i].begin(),adj[i].end());
adj[i].erase(unique(adj[i].begin(),adj[i].end()),adj[i].end());
}
int d[N][N];
for(A=1;A<K;A++)for(B=1;B<K;B++)for(o=1;o<=tot;o++){
U S=mask[o];
for(i=0;i<n;i++)for(j=0;j<i;j++)d[i][j]=d[j][i]=(S>>id[i][j]&1)?B:A;
for(i=0;i<n;i++)d[i][i]=0;
for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)umin(d[i][j],d[i][k]+d[k][j]);
int sum=0;
for(i=0;i<n;i++)for(j=0;j<n;j++)sum+=d[i][j];
apsp[A][B][o]=sum;
}
}
void reorder(int x,int vis){
if(x==n){
U now=0;
for(int i=0;i<n;i++)for(int j=0;j<i;j++)if(g[perm[i]][perm[j]])now|=1U<<id[i][j];
if(minS>now)minS=now;
return;
}
P mindeg(~0U>>1,0);
for(int i=0;i<n;i++)if(!(vis>>i&1)&&mindeg>ident[i])mindeg=ident[i];
for(int i=0;i<n;i++)if(!(vis>>i&1)&&mindeg==ident[i]){
perm[x]=i;
reorder(x+1,vis|(1<<i));
}
}
U adjust(U S){
int i,j;
for(i=0;i<n;i++)deg[i]=0;
for(i=0;i<n;i++)for(j=0;j<i;j++){
g[i][j]=g[j][i]=S>>id[i][j]&1;
if(g[i][j])deg[i]++,deg[j]++;
}
for(i=0;i<n;i++){
two[i]=0;
for(j=0;j<n;j++)if(g[i][j])two[i]+=w[deg[j]];
}
for(i=0;i<n;i++)ident[i]=P(deg[i],two[i]);
minS=~0U;
int vis=0,cnt=0;
for(i=0;i<n;i++)if(deg[i]==0){
vis|=1<<i;
perm[cnt++]=i;
}
for(i=0;i<n;i++)if(deg[i]==n-1){
vis|=1<<i;
perm[cnt++]=i;
}
reorder(cnt,vis);
return minS;
}
int dfs(U S){
S=adjust(S);
int&x=T[S];
if(x)return x;
x=++tot;
mask[tot]=S;
for(int i=0;i<m;i++)if(!(S>>i&1)){
int y=dfs(S^(1U<<i));
adj[x].emplace_back(y);
adj[y].emplace_back(x);
}
return x;
}
void solve(int cnt){
for(int j=1;j<=tot;j++)f[cnt+1][j]=0;
for(int i=cnt;i;i--){
int A=a[i],B=b[i];
for(int j=1;j<=tot;j++){
int cur=-inf;
for(const auto&k:adj[j])umax(cur,apsp[A][B][k]-f[i+1][k]);
f[i][j]=cur;
}
}
printf("%d\n",f[1][1]);
}
}info[N];
int main(){
for(int i=0;i<N;i++)w[i]=(rand()<<15)^rand();
for(int i=2;i<=8;i++)info[i].init(i);
int Case;
scanf("%d",&Case);
while(Case--){
int n,cnt;
scanf("%d%d",&n,&cnt);
for(int i=1;i<=cnt;i++)scanf("%d%d",&a[i],&b[i]);
info[n].solve(cnt);
}
}
C. 最優(yōu) K 子段
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef pair<int,int>P;
const int N=200005;
int Case,n,k,i,j,a[N];bool vis[N],is_prime[N],OK;
int L,R,MID,ANS;
set<P>T;
inline void ins(int sum,int ptr){
T.insert(P(sum,ptr));
}
inline bool valid(int sum,int ptr){
for(set<P>::iterator it=T.begin();it!=T.end();it++){
if(sum-it->first<MID)return 0;
if(is_prime[ptr-it->second])return 1;
}
return 0;
}
inline bool check(){
for(int cur=1,ptr=1;cur<=k;cur++){
if(ptr>n)return 0;
T.clear();
ins(0,ptr-1);
for(int sum=0;;ptr++){
if(ptr>n)return 0;
sum+=a[ptr];
if(valid(sum,ptr)){
ptr++;
break;
}
ins(sum,ptr);
}
}
return 1;
}
int main(){
for(i=2;i<N;i++)if(!vis[i]){
is_prime[i]=1;
for(j=i;j<N;j+=i)vis[j]=1;
}
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>Case;
while(Case--){
cin>>n>>k;
L=R=OK=0;
for(i=1;i<=n;i++){
cin>>a[i];
if(a[i]>0)R+=a[i];else L+=a[i];
}
while(L<=R){
MID=(L+R)/2;
if(check()){
OK=1;
ANS=MID;
L=MID+1;
}else R=MID-1;
}
if(OK)cout<<ANS<<"\n";else cout<<"impossible\n";
}
}
D. 分組
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=21,M=10,LEN=(1<<M)+5;
int Case,n,m,i,ans,val[N],w[LEN],q[LEN],at[LEN];
bool fl[N][LEN],fr[N][LEN];
inline bool cmp(int x,int y){return w[x]<w[y];}
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
void dfs(int x,int suml,int sumr){
if(x==n){
for(int i=0,ml=-1,mr=-1;i<1<<m;i++){
int o=q[i];
if(fl[n][o]&&w[o]>=w[o^suml]){
umax(ml,w[o^suml]);
if(~mr)umin(ans,w[o]-min(w[o^suml],mr));
}
if(fr[n][o]&&w[o]>=w[o^sumr]){
umax(mr,w[o^sumr]);
if(~ml)umin(ans,w[o]-min(w[o^sumr],ml));
}
}
return;
}
int v=val[x];
for(int i=0;i<1<<m;i++){
fl[x+1][i]=fl[x][i]|fl[x][i^v];
fr[x+1][i]=fr[x][i];
}
dfs(x+1,suml^v,sumr);
for(int i=0;i<1<<m;i++){
fl[x+1][i]=fl[x][i];
fr[x+1][i]=fr[x][i]|fr[x][i^v];
}
dfs(x+1,suml,sumr^v);
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)scanf("%d",&val[i]);
for(i=0;i<1<<m;i++)scanf("%d",&w[i]),q[i]=i;
sort(q,q+(1<<m),cmp);
for(i=0;i<1<<m;i++)at[q[i]]=i;
for(i=0;i<1<<m;i++)fl[1][i]=fr[1][i]=0;
fl[1][0]=fr[1][0]=1;
fl[1][val[0]]=1;
ans=~0U>>1;
dfs(1,val[0],0);
printf("%d\n",ans);
}
}
E. 多層血條
#include<cstdio>
const int N=805;
int Case,n,m,hp,dmg,i,j;char f[N];
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d%d%d",&n,&m,&hp,&dmg);
for(i=0;i<m;i++)f[i]=' ';
int top=(hp-1)/m;
int lim=(hp-1)%m;
int col=top%5+'A';
int nxt=(top+4)%5+'A';
if(top)for(i=0;i<m;i++)f[i]=nxt;
for(i=0;i<=lim;i++)f[i]=col;
if(dmg>m)dmg=m;
while(dmg--){
f[lim]='.';
lim=(lim+m-1)%m;
}
putchar('+');
for(i=0;i<m;i++)putchar('-');
puts("+");
for(i=0;i<n;i++){
putchar('|');
for(j=0;j<m;j++)putchar(f[j]);
puts("|");
}
putchar('+');
for(i=0;i<m;i++)putchar('-');
puts("+");
}
}
F. 延時操控
#include<cstdio>
const int N=55,K=5,P=1000000007;
const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int Case,n,m,delay,hp,px,py,ex,ey,i,j,k,x,y,d,lim,o;
int f[2][N][N][K][K*2][K*2],g[2][N][N],ans;
bool ban[N][N];
char ch[N];
inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;}
inline bool check(int x,int y){
if(x<1||x>n||y<1||y>n)return 0;
return !ban[x][y];
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d%d%d",&n,&m,&delay,&hp);
for(i=1;i<=n;i++){
scanf("%s",ch+1);
for(j=1;j<=n;j++){
if(ch[j]=='#')ban[i][j]=1;else ban[i][j]=0;
if(ch[j]=='P')px=i,py=j;
if(ch[j]=='E')ex=i,ey=j;
}
}
ex-=px,ey-=py;
for(o=0;o<2;o++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){
lim=k-(x>0?x:-x);
for(y=-lim;y<=lim;y++)f[o][i][j][k][x+K][y+K]=0;
}
for(o=0;o<2;o++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[o][i][j]=0;
m-=delay;
f[0][px][py][0][K][K]=1;
o=0;
while(m--){
for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){
lim=k-(x>0?x:-x);
for(y=-lim;y<=lim;y++)f[o^1][i][j][k][x+K][y+K]=0;
}
for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){
lim=k-(x>0?x:-x);
for(y=-lim;y<=lim;y++){
int now=f[o][i][j][k][x+K][y+K];
if(!now)continue;
for(d=0;d<4;d++){
px=i+dx[d],py=j+dy[d];
if(!check(px,py))continue;
if(check(px+ex+x,py+ey+y))up(f[o^1][px][py][k][x+K][y+K],now);
else if(k+1==hp)up(g[0][px][py],now);
else up(f[o^1][px][py][k+1][x-dx[d]+K][y-dy[d]+K],now);
}
}
}
o^=1;
}
o=0;
while(delay--){
for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[o^1][i][j]=0;
for(i=1;i<=n;i++)for(j=1;j<=n;j++){
int now=g[o][i][j];
if(!now)continue;
for(d=0;d<4;d++){
px=i+dx[d],py=j+dy[d];
if(!check(px,py))continue;
up(g[o^1][px][py],now);
}
}
o^=1;
}
ans=0;
for(i=1;i<=n;i++)for(j=1;j<=n;j++)up(ans,g[o][i][j]);
printf("%d\n",ans);
}
}
G. 序列更新
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=250005;
int Case,n,q,lim,i,k,x,a[N],b[N],c[N],cs,ct,S[N],T[N];
long long sum;
inline void fix(int&x){
while(x<0)x+=n;
while(x>=n)x-=n;
}
inline void gao(int x,int y){
fix(x);
fix(y);
if(a[x]>=b[y])return;
sum+=b[y]-a[x];
a[x]=b[y];
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>Case;
while(Case--){
cin>>n>>q;
sum=0;
for(i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
for(i=0;i<n;i++)cin>>b[i];
for(i=0;i<n;i++)c[i]=b[i];
sort(c,c+n);
lim=sqrt(n);
lim=max(lim,1);
lim=min(lim,n);
lim=c[n-lim];
cs=ct=0;
for(i=0;i<n;i++){
if(a[i]<=lim)S[cs++]=i;
if(b[i]>lim)T[ct++]=i;
}
while(q--){
cin>>k;
for(i=0;i<cs;){
x=S[i];
gao(x,x+k);
if(a[x]>lim)swap(S[i],S[--cs]);else i++;
}
for(i=0;i<ct;i++){
x=T[i];
gao(x-k,x);
}
cout<<sum<<"\n";
}
}
}
H. 魔法卡牌
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
const int N=63,inf=~0U>>1;
int Case,n,m,i,j,x,y,a[N],b[N],T[N],a_deg[N],b_deg[N];
ull a_all[N],a_ban[N],a_must[N],b_ban[N],nei[N],imp;
bool a_imp[N],can[N][N][2][2];
struct P{
int val;ull way;
P(){}
P(int _val,ull _way){val=_val;way=_way;}
void clr(){val=-inf;way=0;}
void up(const P&b,int k=0){
if(val>b.val+k)return;
if(val<b.val+k){
val=b.val+k;
way=b.way;
return;
}
way+=b.way;
}
void print(){printf("%d %llu\n",val,way);}
};
P dfs(ull S){
if(!S)return P(0,1);
int who=-1,best=inf;
int cnt=__builtin_popcountll(S);
if(imp&S)who=__builtin_ctzll(imp&S);
else for(ull Q=S;Q;Q-=Q&-Q){
int x=__builtin_ctzll(Q);
if(__builtin_popcountll(nei[x]&S)<=2)continue;
int a_deg=__builtin_popcountll(a_all[x]&S);
int b_deg=__builtin_popcountll(b_ban[x]&S);
int now=T[cnt-a_deg-1]+T[cnt-b_deg-1];
if(now<best)who=x,best=now;
}
if(who<0){
P ans(0,1);
for(ull Q=S;Q;){
int head=__builtin_ctzll(Q);
Q-=Q&-Q;
ull mask=S&nei[head];
if(!mask){
S^=1ULL<<head;
ans.val+=max(a[head],b[head]);
if(a[head]==b[head])ans.way*=2;
continue;
}
if((mask&-mask)!=mask)continue;
S^=1ULL<<head;
static P dp[2][2];
int x=head,o=0;
for(int i=0;i<2;i++)dp[0][i].clr();
dp[0][0]=P(a[x],1);
dp[0][1]=P(b[x],1);
while(S&nei[x]){
int y=__builtin_ctzll(S&nei[x]);
S^=1ULL<<y;
for(int j=0;j<2;j++)dp[o^1][j].clr();
for(int j=0;j<2;j++)if(dp[o][j].way){
if(can[x][y][j][0])dp[o^1][0].up(dp[o][j],a[y]);
if(can[x][y][j][1])dp[o^1][1].up(dp[o][j],b[y]);
}
o^=1;
x=y;
}
P cur(-inf,0);
for(int j=0;j<2;j++)if(dp[o][j].way)cur.up(dp[o][j]);
if(!cur.way)return P(-inf,0);
ans.val+=cur.val;
ans.way*=cur.way;
Q&=S;
}
while(S){
int head=__builtin_ctzll(S);
S^=1ULL<<head;
static P dp[2][2][2];
int x=head,o=0;
for(int i=0;i<2;i++)for(int j=0;j<2;j++)dp[0][i][j].clr();
dp[0][0][0]=P(a[x],1);
dp[0][1][1]=P(b[x],1);
while(S&nei[x]){
int y=__builtin_ctzll(S&nei[x]);
S^=1ULL<<y;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)dp[o^1][i][j].clr();
for(int j=0;j<2;j++)if(dp[o][i][j].way){
if(can[x][y][j][0])dp[o^1][i][0].up(dp[o][i][j],a[y]);
if(can[x][y][j][1])dp[o^1][i][1].up(dp[o][i][j],b[y]);
}
}
o^=1;
x=y;
}
P cur(-inf,0);
for(int i=0;i<2;i++)for(int j=0;j<2;j++)
if(dp[o][i][j].way&&can[head][x][i][j])cur.up(dp[o][i][j]);
if(!cur.way)return P(-inf,0);
ans.val+=cur.val;
ans.way*=cur.way;
}
return ans;
}
S^=1ULL<<who;
P ans(-inf,0);
for(int o=0;o<2;o++){
ull nS=S,SA=0,SB=0,Q=0;
int val=0;
if(!o){
if(a_imp[who])continue;
val=a[who];
SA^=a_must[who]&nS;
SB^=a_ban[who]&nS;
Q=a_all[who]&S;
}else{
val=b[who];
SB^=b_ban[who]&nS;
Q=b_ban[who]&nS;
}
nS^=Q;
while(Q){
int x=__builtin_ctzll(Q);
if(SA>>x&1){
val+=a[x];
if(a_ban[x]&SA)break;
if(a_must[x]&SB)break;
if(a_imp[x])break;
SA^=a_must[x]&nS;
SB^=a_ban[x]&nS;
Q^=a_all[x]&nS;
nS^=a_all[x]&nS;
}else{
val+=b[x];
if(b_ban[x]&SA)break;
SB^=b_ban[x]&nS;
Q^=b_ban[x]&nS;
nS^=b_ban[x]&nS;
}
Q^=1ULL<<x;
}
if(Q)continue;
P res=dfs(nS);
ans.up(res,val);
}
return ans;
}
int main(){
for(i=0;i<N;i++){
if(i<=3)T[i]=1;
else T[i]=max(T[i-1]+T[max(i-5,0)],max(T[i-2]+T[i-4],T[i-3]+T[i-3]));
//printf("T[%d]=%d\n",i,T[i]);
}
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
for(i=0;i<n;i++){
scanf("%d%d",&a[i],&b[i]);
a_ban[i]=a_must[i]=b_ban[i]=0;
}
for(i=0;i<n;i++)for(j=0;j<n;j++)for(x=0;x<2;x++)for(y=0;y<2;y++)can[i][j][x][y]=1;
while(m--){
char op[9];
scanf("%s%d%d",op,&x,&y);
x--;y--;
if(op[0]=='A'){
//x -> !y
//y -> !x
a_ban[x]|=1ULL<<y;
a_ban[y]|=1ULL<<x;
can[x][y][0][0]=0;
can[y][x][0][0]=0;
}else{
//x -> y
//!y -> !x
a_must[x]|=1ULL<<y;
b_ban[y]|=1ULL<<x;
can[x][y][0][1]=0;
can[y][x][1][0]=0;
}
}
imp=0;
for(i=0;i<n;i++){
a_imp[i]=!!(a_ban[i]&a_must[i]);
if(a_imp[i])imp|=1ULL<<i;
a_all[i]=a_ban[i]|a_must[i];
nei[i]=a_all[i]|b_ban[i];
}
P ans=dfs((1ULL<<n)-1);
ans.print();
}
}
I. 昵稱檢索
#include<iostream>
#include<string>
using namespace std;
const int N=1000005,day[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int Case,n,m,i,j,x,ans,suf[N],f[N][26],vis[26];string a;
inline int godate(int*s){
int x=m+1;
for(int i=3;~i;i--){
x--;
if(x<1)return 0;
x=f[x][s[i]];
}
return x;
}
inline int goname(){
int x=0;
for(int i=0;i<a.size();i++){
x++;
if(x>m)return m+1;
x=f[x][a[i]-'a'];
}
return x;
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>Case;
while(Case--){
cin>>n>>m>>a;
for(j=0;j<10;j++)vis[j]=0;
for(i=1;i<=m;i++){
if(a[i-1]>='0'&&a[i-1]<='9')vis[a[i-1]-'0']=i;
for(j=0;j<10;j++)f[i][j]=vis[j];
}
for(i=0;i<=m+1;i++)suf[i]=0;
for(i=1;i<=12;i++)for(j=1;j<=day[i];j++){
static int pool[4];
pool[0]=i/10;
pool[1]=i%10;
pool[2]=j/10;
pool[3]=j%10;
x=godate(pool);
if(x)suf[x]++;
}
for(i=m;i>1;i--)suf[i-1]+=suf[i];
for(j=0;j<26;j++)vis[j]=m+1;
for(i=m;i;i--){
if(a[i-1]>='a'&&a[i-1]<='z')vis[a[i-1]-'a']=i;
for(j=0;j<26;j++)f[i][j]=vis[j];
}
ans=0;
while(n--){
cin>>a;
x=goname();
if(x<m)ans+=suf[x+1];
}
cout<<ans<<"\n";
}
}
J. 矩陣的周期
#include<cstdio>
typedef unsigned long long ull;
const int N=63,M=1200005;
int Case,n,m,o,i,j,k,at[N],w[N],lim[N],nxt[M];
bool g[N][N],h[N][N],can[N][N];
ull adj[N],sub0[(1<<20)+1],sub1[(1<<20)+1],sub2[(1<<20)+1],f[M];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int lcm(int a,int b){return a/gcd(a,b)*b;}
inline int getlim(int o,int x){
if(!can[o][x])return 1;
if(w[o]>1||w[x]>1||at[o]==at[x])return n;
int ret=1;
for(int i=0;i<n;i++)if(can[o][i]&&can[i][x])ret=lcm(ret,w[i]);
return ret;
}
inline int getper(int x){
int m=lim[x],i,j;
for(nxt[1]=j=0,i=2;i<=m;nxt[i++]=j){
while(j&&((f[j+1]^f[i])>>x&1))j=nxt[j];
if(!((f[j+1]^f[i])>>x&1))j++;
}
return m-nxt[m];
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=0;i<n;i++){
char ch[N];
scanf("%s",ch);
adj[i]=0;
for(j=0;j<n;j++){
g[i][j]=ch[j]=='1';
if(g[i][j])adj[i]|=1ULL<<j;
}
}
for(i=0;i<n;i++)for(j=0;j<n;j++)can[i][j]=g[i][j]|(i==j);
for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)can[i][j]|=can[i][k]&can[k][j];
for(i=0;i<n;i++)w[i]=0;
for(i=0;i<n;i++){
if(w[i])continue;
m=0;
for(j=i;j<n;j++)if(can[i][j]&&can[j][i])m++;
for(j=i;j<n;j++)if(can[i][j]&&can[j][i]){
at[j]=i;
w[j]=m;
}
}
for(o=0;o<N;o++){
for(i=0;i<n;i++)for(j=0;j<n;j++)h[i][j]=0;
for(i=0;i<n;i++)for(j=0;j<n;j++)for(k=0;k<n;k++)h[i][k]|=g[i][j]&g[j][k];
for(i=0;i<n;i++)for(j=0;j<n;j++)g[i][j]=h[i][j];
}
m=1<<(n<20?n:20);
for(i=0;i<m;i++)sub0[i]=sub1[i]=sub2[i]=0;
for(i=0;i<n;i++){
j=i;
if(j<20){sub0[1<<j]|=adj[i];continue;}else j-=20;
if(j<20){sub1[1<<j]|=adj[i];continue;}else j-=20;
sub2[1<<j]|=adj[i];
}
for(i=2;i<m;i++){
j=i&-i;
sub0[i]=sub0[i^j]|sub0[j];
sub1[i]=sub1[i^j]|sub1[j];
sub2[i]=sub2[i^j]|sub2[j];
}
for(o=0;o<n;o++){
m=1;
for(i=0;i<n;i++){
lim[i]=getlim(o,i)*2;
if(m<lim[i])m=lim[i];
}
ull S=0;
for(i=0;i<n;i++)if(g[o][i])S|=1ULL<<i;
for(i=1;i<=m;i++){
f[i]=S;
S=sub0[S&1048575]|sub1[S>>20&1048575]|sub2[S>>40];
}
for(i=0;i<n;i++)printf("%d%c",getper(i),i+1<n?' ':'\n');
}
}
}
K. 找環(huán)
#include<iostream>
using namespace std;
typedef unsigned int U;
typedef unsigned long long ull;
const int N=1005,M=2005,TOT=N*M*11,BASE=998244353,P=1000000007;
ull weight[N];
U SX=335634763,SY=873658265,SZ=192849106,SW=746126501;
inline ull xorshift128(){
U t=SX^(SX<<11);
SX=SY;
SY=SZ;
SZ=SW;
return SW=SW^(SW>>19)^t^(t>>8);
}
inline ull myrand(){return (xorshift128()<<32)^xorshift128();}
int Case,inv[N],n,m,i,j,res,f[N][N],tot,l[TOT],r[TOT],val[TOT];ull sum[TOT];
struct E{int x,y,z;}e[M];
struct Frac{
int u1,u2,d;
Frac(){}
Frac(int _u1,int _u2,int _d){u1=_u1,u2=_u2,d=_d;}
};
int ins(int x,int a,int b,int c){
int y=++tot;
val[y]=val[x]+1;
sum[y]=sum[x]+weight[c];
if(a==b)return y;
int mid=(a+b)>>1;
if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];
else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
return y;
}
inline bool smaller(int x,int y){
if(y<0)return 1;
if(sum[x]==sum[y])return 0;
int a=1,b=n,mid;
while(a<b){
mid=(a+b)>>1;
if(sum[r[x]]==sum[r[y]]){
b=mid;
x=l[x];
y=l[y];
}else{
a=mid+1;
x=r[x];
y=r[y];
}
}
return val[x]<val[y];
}
inline int compare(const Frac&A,const Frac&B){
if(A.u1<0&&B.u1<0)return 0;
if(A.u1<0)return 1;
if(B.u1<0)return -1;
int a=1,b=n,mid;
int A1=A.u1,A2=A.u2,B1=B.u1,B2=B.u2,AD=A.d,BD=B.d;
if((sum[A1]-sum[A2])*BD==(sum[B1]-sum[B2])*AD)return 0;
//(A1-A2)/AD<(B1-B2)/BD
//(A1-A2)*BD<(B1-B2)*AD
while(a<b){
mid=(a+b)>>1;
if((sum[r[A1]]-sum[r[A2]])*BD==(sum[r[B1]]-sum[r[B2]])*AD){
b=mid;
A1=l[A1];
A2=l[A2];
B1=l[B1];
B2=l[B2];
}else{
a=mid+1;
A1=r[A1];
A2=r[A2];
B1=r[B1];
B2=r[B2];
}
}
int cross=(val[A1]-val[A2])*BD-(val[B1]-val[B2])*AD;
if(!cross)return 0;
return cross<0?-1:1;
}
void cal(int x,int y,int a,int b){
if(a==b){
res=(1LL*res*BASE+val[x]-val[y])%P;
return;
}
int mid=(a+b)>>1;
cal(r[x],r[y],mid+1,b);
cal(l[x],l[y],a,mid);
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>Case;
for(inv[0]=inv[1]=1,i=2;i<N;i++)inv[i]=1LL*(P-P/i)*inv[P%i]%P;
while(Case--){
cin>>n>>m;
for(i=1;i<=m;i++)cin>>e[i].x>>e[i].y>>e[i].z;
for(i=1;i<=n;i++)weight[i]=myrand();
for(i=0;i<=n+1;i++)for(j=1;j<=n;j++)f[i][j]=-1;
for(j=1;j<=n;j++)f[0][j]=0;
for(i=0;i<=n;i++)for(j=1;j<=m;j++){
int x=e[j].x,y=e[j].y,z=e[j].z;
int root=f[i][x];
if(root<0)continue;
int now=ins(root,1,n,z+1);
if(smaller(now,f[i+1][y]))f[i+1][y]=now;
}
Frac ans=Frac(-1,-1,1);
for(i=1;i<=n;i++){
int fin=f[n+1][i];
if(fin<0)continue;
Frac me=Frac(0,0,1);
for(j=0;j<=n;j++){
int now=f[j][i];
if(now<0)continue;
Frac tmp(fin,now,n+1-j);
if(compare(tmp,me)>0)me=tmp;
}
if(compare(me,ans)<0)ans=me;
}
if(ans.u1<0)cout<<"-1\n";
else{
res=0;
cal(ans.u1,ans.u2,1,n);
res=1LL*res*inv[ans.d]%P;
cout<<res<<"\n";
}
for(i=1;i<=tot;i++)l[i]=r[i]=val[i]=sum[i]=0;
tot=0;
}
}
L. 尋找寶藏
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=300005;
int Case,n,m,i;ll bit[N];vector<int>gl[N],gr[N];
struct E{int y,w;ll pre,suf,val;}e[N];
struct Qry{int yl,yr;ll ans,ur,ru;}q[N];
inline void up(ll&a,ll b){a<b?(a=b):0;}
inline void ins(int x,ll p){for(;x<=n;x+=x&-x)up(bit[x],p);}
inline ll ask(int x){
ll t=0;
for((x>n)&&(x=n);x;x-=x&-x)up(t,bit[x]);
return t;
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>Case;
while(Case--){
cin>>n>>m;
for(i=1;i<=n;i++){
cin>>e[i].y>>e[i].w;
gl[i].clear();
gr[i].clear();
}
for(i=1;i<=m;i++){
int xl,xr;
cin>>xl>>q[i].yl>>xr>>q[i].yr;
gl[xl].emplace_back(i);
gr[xr].emplace_back(i);
}
for(i=1;i<=n;i++)bit[i]=0;
for(i=1;i<=n;i++){
for(const auto&j:gl[i])q[j].ur=ask(q[j].yr);
e[i].pre=ask(e[i].y)+e[i].w;
ins(e[i].y,e[i].pre);
for(const auto&j:gr[i])q[j].ru=ask(q[j].yl-1);
}
for(i=0;i<=n;i++)bit[i]=0;
for(i=n;i;i--){
for(const auto&j:gr[i])q[j].ru+=ask(n+1-q[j].yl);
e[i].suf=ask(n+1-e[i].y)+e[i].w;
ins(n+1-e[i].y,e[i].suf);
e[i].val=e[i].pre+e[i].suf-e[i].w;
for(const auto&j:gl[i])q[j].ur+=ask(n+1-(q[j].yr+1));
}
for(i=1;i<=m;i++)q[i].ans=max(q[i].ur,q[i].ru);
for(i=1;i<=n;i++)bit[i]=0;
for(i=1;i<=n;i++){
for(const auto&j:gl[i])up(q[j].ans,ask(n+1-(q[j].yr+1)));
ins(n+1-e[i].y,e[i].val);
}
for(i=1;i<=n;i++)bit[i]=0;
for(i=n;i;i--){
for(const auto&j:gr[i])up(q[j].ans,ask(q[j].yl-1));
ins(e[i].y,e[i].val);
}
for(i=1;i<=m;i++)cout<<q[i].ans<<"\n";
}
}

浙公網(wǎng)安備 33010602011771號