21牛客多校第八场
A
签到题,注意\(x=0\)的特例,求逆元即可
#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 4933
#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 qp(int x,int t,int res=1)
{
for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
return res;
}
int n,m,k,a,l;
int main()
{
n=read(),m=read(),k=read(),a=read(),l=read();
int x,y,z,res=1;
rep(i,1,k) {x=read(),y=read(),z=read();if(x) res=mul(res,qp(z,MOD-2,z-y));}
printf("%d\n",pls(res,a));
}
D
由于\(a+b=(a|b)+(a\&b)\),则每一位的限制是独立的,分别\(O(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 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,b[MAXN],c[MAXN],ans=1;
inline int cheq(int x,int j)
{
rep(i,2,n)
{
if((c[i]>>j)&1){if(!x) return 0;}
else if((b[i]>>j)&1) x^=1;
else {if(x) return 0;}
}
return 1;
}
int main()
{
n=read();
rep(i,2,n) b[i]=read();
rep(i,2,n) {c[i]=read(),c[i]-=b[i];if(c[i]<0) return puts("0"),0;}
dwn(j,29,0)
{
if((c[2]>>j)&1)
{if(!cheq(1,j)) return puts("0"),0;}
else if((b[2]>>j)&1)
{
int tmp=cheq(1,j)+cheq(0,j);
if(!tmp) return puts("0"),0;
else ans*=tmp;
}
else
{if(!cheq(0,j)) return puts("0"),0;}
}
printf("%d\n",ans);
}
E
签到题 \(puts("no")\)
#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 main()
{
rep(T,1,read())
{
puts("no");
}
}
F
考虑按照列分治,每次分治处理出\(mid\)两侧的点分别能到达\(mid\)这一列的哪些点
用\(bitset\)记录,这一部分复杂度为\(O(\frac{n^2mlogm}{w})\)
把所有询问挂到起点的位置,每次分治都可以计算出询问点的列在\([l,r]\)范围内且 起点与终点分别位于\(mid\)两侧的答案
注意终点列在\(mid\)时需要特殊处理
#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 500100
#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,ans[MAXN],cur[550][550];
struct Ask{int x,y,id;}g;
bool operator < (Ask &a,Ask &b) {return a.y<b.y;}
char ch[550][550];
bitset<505> f[510][510];
vector<Ask> q[550][550];
void Div(int l,int r)
{
int mid=l+r>>1;if(l<mid) Div(l,mid-1);if(mid<r) Div(mid+1,r);
rep(i,1,n)
{
f[i][mid].reset();
if(ch[i][mid]=='0')
{
f[i][mid][i]=1;
if(i!=1) f[i][mid]|=f[i-1][mid];
}
}
rep(j,mid+1,r) rep(i,1,n) if(ch[i][j]!='1')
{
if(i!=1) f[i][j]=f[i-1][j]|f[i][j-1];
else f[i][j]=f[i][j-1];
}
dwn(i,n,1)
{
f[i][mid].reset();
if(ch[i][mid]=='0')
{
f[i][mid][i]=1;
if(i!=n) f[i][mid]|=f[i+1][mid];
}
}
dwn(j,mid-1,l) dwn(i,n,1) if(ch[i][j]!='1')
{
if(i!=n) f[i][j]=f[i+1][j]|f[i][j+1];
else f[i][j]=f[i][j+1];
}
rep(j,l,mid) rep(i,1,n) if(q[i][j].size())
for(int &st=cur[i][j],ed=q[i][j].size()-1;st<=ed;st++)
{
g=q[i][j][st];if(g.y>r) break;
if(g.y==mid) ans[g.id]=f[i][j][g.x];
else ans[g.id]=(f[i][j]&f[g.x][g.y]).any();
}
}
int main()
{
n=read(),m=read();int Q,x,a,b,c,d;
rep(i,1,n) scanf("%s",ch[i]+1);
Q=read();rep(i,1,Q)
{
x=read(),a=read(),b=read(),c=read(),d=read();
if(x==1) {if(b==d&&a<=c) q[a][b].pb({c,d,i});}
else if(x==2) {if(a==c&&b<=d) q[a][b].pb({c,d,i});}
else if(a<=c&&b<=d) q[a][b].pb({c,d,i});
}
rep(i,1,n) rep(j,1,m) if(q[i][j].size())
sort(q[i][j].begin(),q[i][j].end());
Div(1,m);rep(i,1,Q) puts(ans[i]?"yes":"no");
}
J
\(dp\)出不在\(s\rightarrow t\)链上的点离开的最长链,则题目转化为链上的博弈
例如对于\((x,y,0)\)这个状态,表示两人在\((x,y)\)位置,当前决策人是\(x\)
当前的决策人要么继续向前走一步,要么选择离开这条链,对手则可以在\((x+1,y)\)内选择一个最大值离开
容易发现维护一个\(RMQ\)之后状态只有\(O(n)\)个,直接\(dfs\)模拟即可,而这个\(RMQ\)可以在递归的过程中维护
#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 500100
#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,dp[MAXN],in[MAXN],fa[MAXN];
int s,t,g[MAXN],tot,w1[MAXN],w2[MAXN],mx1,mx2;
void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
void getf(int x,int pa)
{
fa[x]=pa;ren if(to[i]^pa) getf(to[i],x);
}
void dfs(int x,int pa)
{
ren if(to[i]^pa)
{
dfs(to[i],x);
if(!in[to[i]]) dp[x]=max(dp[x],dp[to[i]]+1);
}
}
int solve(int x,int y,int now)
{
if(y==x+1)
{
mx1=max(w1[x],w1[y]),mx2=max(w2[x],w2[y]);
return w1[x]-w2[y];
}
int res=now?solve(x,y-1,now^1):solve(x+1,y,now^1);
if(!now) res=max(res,w1[x]-mx2),mx1=max(mx1,w1[x]),mx2=max(mx2,w2[x]);
else res=min(res,mx1-w2[y]),mx1=max(mx1,w1[y]),mx2=max(mx2,w2[y]);
return res;
}
int main()
{
n=read(),s=read(),t=read();int a,b;
rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a);
getf(s,0);for(a=t;a;a=fa[a]) {in[a]=1;g[++tot]=a;}
dfs(s,0);n=tot;rep(i,1,n>>1) swap(g[i],g[n-i+1]);
rep(i,1,n) w1[i]=i-1+dp[g[i]],w2[i]=n-i+dp[g[i]];
printf("%d\n",solve(1,n,0));
}
K
对于一个直线要么沿着短边前进获得\(2\)的贡献,要么沿着对角线走获得\(3\)的贡献
不妨令\(a,b\)分别表示短边和对角线长度,则答案为\(max\{2x+3y+4\},xa+yb\le \pi;x,y\in N\)
显然\(x,y\)不能超过\(2\),否则根据\(3a\)与\(2b\)的大小关系一定能得到更优的解
直接枚举这个较小数即可
#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;
}
const db pi=acos(-1);
db a,b;int ans;
int main()
{
rep(T,1,read())
{
cin>>a>>b;if(a>b) swap(a,b);
b=sqrt(a*a+b*b);ans=0;
rep(i,0,2)
{
if(i*b<pi) ans=max(ans,3*i+2*(int)((pi-i*b)/a));
if(i*a<pi) ans=max(ans,2*i+3*(int)((pi-i*a)/b));
}
printf("%d\n",ans+4);
}
}