2022杭电多校Day1
01
考虑 z 函数,对于每个 $p=G_{len}-x+1$,它能贡献的 $G_{len}$ 满足 $p\leq G_{len}< p+z[p]$ 且 $G_{len}-p+1$ 是 $k$ 的倍数,用差分维护。
Problem 01
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
void Z(char *s,int *z)
{
int n=strlen(s);
z[0]=0;
for(int i=1,l=0,r=0;i<n;i++)
{
if(i<=r&&z[i-l]<r-i+1)
z[i]=z[i-l];
else
{
z[i]=max(0,r-i+1);
while(i+z[i]<n&&s[z[i]]==s[i+z[i]]) z[i]++;
}
if(i+z[i]-1>r)
{
l=i;
r=i+z[i]-1;
}
}
z[0]=n;
}
char s[1001000];
int z[1001000];
int delta[2001000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(delta,0,sizeof(delta));
scanf("%s",s+1);
int k,n;
scanf("%d",&k);
n=strlen(s+1);
Z(s+1,z+1);
for(int i=1;i<=n;i++)
{
int fst=min(n+1,i+i+k-2);
if(z[i]+i-1<min(n+1,i+i+k-2))
continue;
int lst=(z[i]+i-1-min(n+1,i+i+k-2))/k*k+min(n+1,i+i+k-2);
delta[fst]++;
delta[lst+k]--;
}
ll ans=1;
for(int i=1;i<=n;i++)
{
if(i>k)
delta[i]+=delta[i-k];
ans=ans*(delta[i]+1)%998244353;
}
cout<<ans<<endl;
}
return 0;
}
02
签到题,枚举删除了哪些墙判断联通性即可。
Problem 02
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
bool f[22][22][22][22];
pii fa[22][22];
pii fa2[22][22];
int x1[22],y1[22],x2[22],y2[22];
pii anc(pii x)
{
if(fa[x.first][x.second]==x)
return x;
return fa[x.first][x.second]=anc(fa[x.first][x.second]);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie();
cout.tie();
int t;
cin>>t;
while(t--)
{
// memset(f,0,sizeof(f));
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
fa[i][j]=mp(i,j);
int sx,sy,tx,ty;
cin>>sx>>sy>>tx>>ty;
for(int i=0;i<k;i++)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
if(x1==x2&&y1>y2)
swap(y1,y2);
if(y1==y2&&x1>x2)
swap(x1,x2);
if(x1==x2&&x1&&x1<n)
for(int i=y1;i<y2;i++)
f[x1-1][i][x1][i]=1,f[x1][i][x1-1][i]=1;
else if(y1==y2&&y1&&y1<m)
for(int i=x1;i<x2;i++)
f[i][y1-1][i][y1]=1,f[i][y1][i][y1-1]=1;
::x1[i]=x1;
::x2[i]=x2;
::y1[i]=y1;
::y2[i]=y2;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
for(int i2=max(0,i-1);i2<min(i+2,n);i2++)
for(int j2=max(0,j-1);j2<min(j+2,m);j2++) if(abs(i-i2)+abs(j-j2)==1)
if(!f[i][j][i2][j2])
{
pii p=anc(mp(i,j));
fa[p.first][p.second]=anc(mp(i2,j2));
}
memcpy(fa2,fa,sizeof(fa));
int ans=k;
for(int msk=0;msk<(1<<k);msk++) if(__builtin_popcount(msk)<ans)
{
for(int i=0;i<k;i++) if(msk>>i&1)
{
int x1=::x1[i],y1=::y1[i],x2=::x2[i],y2=::y2[i];
if(x1==x2&&x1&&x1<n)
for(int i=y1;i<y2;i++)
{
pii p=anc(mp(x1-1,i));
fa[p.first][p.second]=anc(mp(x1,i));
}
else if(y1==y2&&y1&&y1<m)
for(int i=x1;i<x2;i++)
{
pii p=anc(mp(i,y1-1));
fa[p.first][p.second]=anc(mp(i,y1));
}
}
if(anc(mp(sx,sy))==anc(mp(tx,ty)))
ans=min(ans,__builtin_popcount(msk));
memcpy(fa,fa2,sizeof(fa));
}
cout<<ans<<endl;
for(int i=0;i<k;i++)
{
int x1=::x1[i],y1=::y1[i],x2=::x2[i],y2=::y2[i];
if(x1==x2&&x1&&x1<n)
for(int i=y1;i<y2;i++)
f[x1-1][i][x1][i]=0,f[x1][i][x1-1][i]=0;
else if(y1==y2&&y1&&y1<m)
for(int i=x1;i<x2;i++)
f[i][y1-1][i][y1]=0,f[i][y1][i][y1-1]=0;
}
}
return 0;
}
03
由于异或最大值不好维护,可以考虑把异或的值也记在状态里,$dp_{i,j,k}$ 表示考虑前 $i$ 个数,异或为 $j$,重量为 $k$ 是否可行,使用 bitset 来优化转移即可。
Problem 03
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
bitset<1024> f[1025][2];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=0;i<1025;i++)
for(int j=0;j<1024;j++)
f[i][0].reset(j),f[i][1].reset(j);
f[0][0].set(0);
int cur=0;
while(n--)
{
int u,v;
cin>>v>>u;
for(int i=0;i<1024;i++)
f[i][cur^1]=f[i][cur]|(f[i^u][cur]<<v);
cur^=1;
}
int ans=-1;
for(int i=0;i<1024;i++)
if(f[i][cur][m])
ans=i;
cout<<ans<<endl;
}
return 0;
}
04
上一题是 bitset 这题肯定不是了吧……对吧……你说呢?
我的做法:
转换成切比雪夫距离求二维前缀和,枚举中位数是哪条边,答案相当于 距离 $p_1$ 长度小于中位数的点数 减去 同时距离 $p_1,p_2$ 的长度都小于中位数的点数。最后求答案时进行简单容斥即可。
官方解法:
枚举中位数,用 bitset 求答案。
Problem 04
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int x[2020],y[2020];
vector<int> vecx,vecy;
int psum[2020][2020];
bool isprime[200200];
map<int,int> cnt;
map<pii,int> Mp;
int main()
{
memset(isprime,1,sizeof(isprime));
isprime[0]=isprime[1]=0;
for(int i=2;i<=1000;i++)
if(isprime[i])
for(int j=i*i;j<200200;j+=i)
isprime[j]=0;
int t;
scanf("%d",&t);
while(t--)
{
vecx.clear();
vecy.clear();
memset(psum,0,sizeof(psum));
Mp.clear();
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",x+i,y+i);
int nx=x[i]+y[i];
int ny=x[i]-y[i]+m+1;
x[i]=nx;
y[i]=ny;
Mp[mp(nx,ny)]++;
vecx.pb(x[i]);
vecy.pb(y[i]);
}
vecx.pb(-1e9);
vecy.pb(-1e9);
srt(vecx);
srt(vecy);
for(int i=1;i<=n;i++)
{
x[i]=lb(vecx,x[i]);
y[i]=lb(vecy,y[i]);
psum[x[i]][y[i]]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
psum[i][j]+=psum[i-1][j]+psum[i][j-1]-psum[i-1][j-1];
ll ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(i!=j)
{
int distij=max(abs(vecx[x[i]]-vecx[x[j]]),abs(vecy[y[i]]-vecy[y[j]]));
if(isprime[distij])
{
int lx,rx,ly,ry;
lx=ub(vecx,vecx[x[i]]-distij);
rx=lb(vecx,vecx[x[i]]+distij)-1;
ly=ub(vecy,vecy[y[i]]-distij);
ry=lb(vecy,vecy[y[i]]+distij)-1;
rx=max(rx,lx-1);
ry=max(ry,ly-1);
int sum1=psum[rx][ry]-psum[lx-1][ry]-psum[rx][ly-1]+psum[lx-1][ly-1];
int lx1,rx1,ly1,ry1;
lx1=ub(vecx,vecx[x[j]]-distij-1);
rx1=lb(vecx,vecx[x[j]]+distij+1)-1;
ly1=ub(vecy,vecy[y[j]]-distij-1);
ry1=lb(vecy,vecy[y[j]]+distij+1)-1;
lx1=max(lx1,lx);
ly1=max(ly1,ly);
rx1=min(rx1,rx);
ry1=min(ry1,ry);
rx1=max(rx1,lx1-1);
ry1=max(ry1,ly1-1);
int sum2=psum[rx1][ry1]-psum[lx1-1][ry1]-psum[rx1][ly1-1]+psum[lx1-1][ly1-1];
ans+=sum1-sum2;
}
}
for(int i=1;i<=n;i++)
{
cnt.clear();
for(int j=1;j<=n;j++)
{
int distij=max(abs(vecx[x[i]]-vecx[x[j]]),abs(vecy[y[i]]-vecy[y[j]]));
if(isprime[distij])
ans+=cnt[distij]++;
}
}
ll ans2=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(i!=j)
{
if(x[i]==x[j])
{
if(y[i]>y[j])
continue;
int dist=vecy[y[j]]-vecy[y[i]];
if(!isprime[dist])
continue;
int xx=lb(vecx,vecx[x[i]]+dist);
if(xx<sz(vecx)&&vecx[xx]==vecx[x[i]]+dist)
ans2+=psum[xx][y[j]-1]-psum[xx][y[i]]-psum[xx-1][y[j]-1]+psum[xx-1][y[i]];
xx=lb(vecx,vecx[x[i]]-dist);
if(xx<sz(vecx)&&vecx[xx]==vecx[x[i]]-dist)
ans2+=psum[xx][y[j]-1]-psum[xx][y[i]]-psum[xx-1][y[j]-1]+psum[xx-1][y[i]];
}
if(y[i]==y[j])
{
if(x[i]>x[j])
continue;
int dist=vecx[x[j]]-vecx[x[i]];
if(!isprime[dist])
continue;
int yy=lb(vecy,vecy[y[i]]+dist);
if(yy<sz(vecy)&&vecy[yy]==vecy[y[i]]+dist)
ans2+=psum[x[j]-1][yy]-psum[x[i]][yy]-psum[x[j]-1][yy-1]+psum[x[i]][yy-1];
yy=lb(vecy,vecy[y[i]]-dist);
if(yy<sz(vecy)&&vecy[yy]==vecy[y[i]]-dist)
ans2+=psum[x[j]-1][yy]-psum[x[i]][yy]-psum[x[j]-1][yy-1]+psum[x[i]][yy-1];
}
}
// for(int i=1;i<=n;i++)
// cout<<vecx[x[i]]<<" "<<vecy[y[i]]<<endl;
ll ans3=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(i!=j)
{
if(x[i]==x[j])
{
// cout<<"# "<<i<<" "<<j<<endl;
int dist=abs(vecy[y[j]]-vecy[y[i]]);
if(!isprime[dist])
continue;
ans3+=Mp[mp(vecx[x[i]]+dist,vecy[y[i]])];
ans3+=Mp[mp(vecx[x[i]]-dist,vecy[y[i]])];
}
if(y[i]==y[j])
{
// cout<<"? "<<i<<" "<<j<<endl;
int dist=abs(vecx[x[j]]-vecx[x[i]]);
if(!isprime[dist])
continue;
ans3+=Mp[mp(vecx[x[i]],vecy[y[i]]+dist)];
ans3+=Mp[mp(vecx[x[i]],vecy[y[i]]-dist)];
}
}
// cout<<ans2<<" "<<ans3<<endl;
ans-=ans2*2;
ans-=ans3;
printf("%lld\n",ans);
}
return 0;
}
05
对于每个点首先预处理它展开之后的字符串的长度(若无限长则设为 $10^{18}$)。类似于树剖的,求出每个点的重儿子,即在展开后的字符串(保留前 $10^{18}$ 个)中占的部分最长的儿子,预处理倍增数组(即每个点的第 $2^k$ 级重儿子),查询时如果在重儿子中则倍增跳,否则二分出是哪个儿子递归即可。
复杂度证明:倍增每跳一次会至少将查询区间(最初始是 $[1,10^{18}]$)减半,每次二分将会以 $\log x$ 的代价将查询区间减小到 $\frac{1}{x}$,故复杂度为 $O((n+q)\log 10^{18})$。
Problem 05
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
vector<int> G[2020];
vector<ll> vec[2020];
ll siz[2020];
char buff[100100];
const ll Max=1e18+10;
int nxt[2020][77];
ll pre[2020][77];
ll suf[2020][77];
void Assert(bool f)
{
if(!f)
{
puts("fuck you,leather man~");
exit(0);
}
}
ll dfs(int u)
{
if(siz[u]>0)
return siz[u];
if(u<=26)
{
siz[u]=1;
nxt[u][0]=0;
pre[u][0]=Max;
suf[u][0]=Max;
return 1;
}
if(siz[u]==-1)
{
siz[u]=Max;
return siz[u];
}
siz[u]=-1;
ll sum=0;
ll mx=0;
for(auto v:G[u])
{
ll s=dfs(v);
s=min(s,Max-sum);
if(s>mx)
{
mx=s;
nxt[u][0]=v;
pre[u][0]=sum;
suf[u][0]=sum+s;
// cout<<u<<" "<<v<<" "<<sum<<endl;
}
sum+=s;
vec[u].pb(sum);
if(sum==Max)
break;
}
// Assert(vec[u].back()==sum);
siz[u]=sum;
return siz[u];
}
char get(int u,ll k)
{
// Assert(k>0);
// cout<<"-"<<u<<" "<<k<<endl;
if(u<=26)
{
if(k==1)
return (u+'a'-1);
return '@';
}
if(siz[u]<k)
return '@';
for(int i=60;i>=0;i--)
if(pre[u][i]<k&&suf[u][i]>=k&&nxt[u][i])
{
// cout<<i<<endl;
// cout<<pre[u][i]<<endl;
// cout<<nxt[u][i]<<endl;
k-=pre[u][i];
u=nxt[u][i];
}
if(u<=26)
{
if(k==1)
return (u+'a'-1);
return '@';
}
int pos=lb(vec[u],k);
return get(G[u][pos],k-(pos>0?vec[u][pos-1]:0));
}
int main()
{
// freopen("in.cpp","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
memset(siz,0,sizeof(siz));
memset(nxt,0,sizeof(nxt));
memset(pre,0,sizeof(pre));
memset(suf,0,sizeof(suf));
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n+26;i++)
{
G[i].clear();
vec[i].clear();
}
for(int i=1;i<=n;i++)
{
scanf("%s",buff);
int len=strlen(buff);
bool f=0;
for(int j=0;j<len;j++)
{
if(buff[j]=='>')
{
f=1;
continue;
}
if(!f)
continue;
if(isalpha(buff[j]))
G[i+26].pb(buff[j]-'a'+1);
else
{
Assert(buff[j]=='[');
int p=j+1;
int x=0;
while(buff[p]!=']')
x=(x<<1)+(x<<3)+(buff[p++]^48);
G[i+26].pb(x+26);
j=p;
}
}
}
for(int i=1;i<=n;i++)
if(!siz[i+26])
dfs(i+26);
for(int i=0;i<61;i++)
for(int j=1;j<=n+26;j++)
{
nxt[j][i+1]=nxt[nxt[j][i]][i];
pre[j][i+1]=min(Max,pre[nxt[j][i]][i]+pre[j][i]);
suf[j][i+1]=min(Max,suf[nxt[j][i]][i]+pre[j][i]);
}
// cout<<pre[28][59]<<endl;
// system("pause");
// for(int i=1;i<=n+26;i++)
// {
// for(auto j:G[i])
// cout<<j<<" ";
// puts("");
// }
// for(int i=1;i<=n+26;i++)
// cout<<siz[i]<<endl;
while(m--)
{
int x;
ll k;
scanf("%d%lld",&x,&k);
char c=get(x+26,k);
if(c=='@')
printf("-1");
else putchar(c);
putchar('\n');
}
}
return 0;
}
08
考虑将每个点 $i$ 拆成两个点 $i$ 和 $i+n$,$i$ 表示上一步不是特殊边,$i+n$ 表示上一步是特殊边。对于正常在边上移动的转移是简单的,对于隔空 tp 的转移,我们可以发现,一个点肯定是第一次被转移到的时候最优(最短路算法一定先考虑 $dist$ 较小的点/转移)。所以可以使用 set 维护还剩哪些点没有被 tp 转移过,每次暴力转移即可。
Problem 08
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int Dist[2002000];
vector<pii> G[2002000];
int nxt[2002000];
int prv[2002000];
bool f[2002000];
map<pii,bool> Mp;
int cc;
signed main()
{
int tc;
scanf("%lld",&tc);
while(tc--)
{
Mp.clear();
int m,n,s,k;
scanf("%lld%lld%lld%lld",&n,&m,&s,&k);
cc=n;
for(int i=1;i<=n+n;i++)
G[i].clear(),f[i]=0;
for(int i=1;i<=n+n;i++)
Dist[i]=1ll*inf*inf;
while(m--)
{
int u,v,w,t;
scanf("%lld%lld%lld%lld",&u,&v,&w,&t);
if(t)
{
G[u+n].pb(mp(v+n,w-k));
G[u].pb(mp(v+n,w));
}
else
{
G[u+n].pb(mp(v,w-k));
G[u].pb(mp(v,w));
}
Mp[mp(u,v)]=1;
}
for(int i=1;i<=n;i++)
nxt[i]=i%n+1;
for(int i=1;i<=n;i++)
prv[nxt[i]]=i;
priority_queue<pii,vector<pii>,greater<pii>> pq;
pq.push(mp(0,s));
Dist[s]=0;
while(!pq.empty())
{
int dist=pq.top().first;
int u=pq.top().second;
pq.pop();
if(dist!=Dist[u])
continue;
if(u>n)
{
int x=u-n;
int y=nxt[x];
while(cc&&f[y])
y=nxt[y];
nxt[x]=y;
if(y!=x&&!f[y])
while(true)
{
if(!Mp[mp(x,y)])
{
if(dist<Dist[y])
{
Dist[y]=dist;
pq.push(mp(dist,y));
}
nxt[prv[y]]=nxt[y];
prv[nxt[y]]=prv[y];
f[y]=1;
cc--;
}
if((y-x+n)%n>=(nxt[y]-x+n)%n)
break;
y=nxt[y];
}
}
for(auto p:G[u])
{
int v=p.first;
int d=p.second;
if(Dist[v]>dist+d)
{
Dist[v]=dist+d;
pq.push(mp(Dist[v],v));
}
}
}
for(int i=1;i<=n;i++)
if(min(Dist[i],Dist[i+n])==1ll*inf*inf)
printf("-1 ");
else printf("%lld ",min(Dist[i],Dist[i+n]));
puts("");
}
return 0;
}
09
不妨设 $1$ 号点一定在横线上(可以通过每次旋转 $45^\circ$ 实现),若所有点均在横线上,则答案为 YES。
否则考虑一个不在横线上的点,从它出发做竖线、左斜线、右斜线交横线为三个点,激光可以放置的点必定在这三个点中,枚举判断即可。
Problem 09
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
void turn(pii &a){a=mp(a.first-a.second,a.first+a.second);}
bool laser(pii p,pii a){return (p.first==a.first)||(p.second==a.second)||(p.first-p.second==a.first-a.second)||(p.first+p.second==a.first+a.second);}
pii pos1(pii p,pii a){return mp(p.first,a.second);};
pii pos2(pii p,pii a){return mp(p.first,a.first+a.second-p.first);};
pii pos3(pii p,pii a){return mp(p.first,p.first-a.first+a.second);};
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
vector<pii> vec;
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
vec.pb(mp(x,y));
}
bool flag=0;
for(int i=0;i<4;i++)
{
bool fl=1;
for(int j=1;j<n;j++)
if(vec[0].first!=vec[j].first)
{
fl=0;
{
bool f=1;
pii p=pos1(vec[0],vec[j]);
for(int x=0;x<n;x++)
f&=laser(p,vec[x]);
fl|=f;
}
{
bool f=1;
pii p=pos2(vec[0],vec[j]);
for(int x=0;x<n;x++)
f&=laser(p,vec[x]);
fl|=f;
}
{
bool f=1;
pii p=pos3(vec[0],vec[j]);
for(int x=0;x<n;x++)
f&=laser(p,vec[x]);
fl|=f;
}
break;
}
flag|=fl;
for(auto &p:vec)
turn(p);
}
if(flag)
puts("YES");
else puts("NO");
}
return 0;
}
11
签到题,输出 \(\frac{n-m}{2}\) 即可。
Problem 11
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int a[1001000];
const ll mod=1e9+7;
ll ksm(ll a,ll b)
{
if(!b)
return 1ll;
if(b%2)
return ksm(a*a%mod,b/2)*a%mod;
return ksm(a*a%mod,b/2);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n,m;
scanf("%lld%lld",&n,&m);
cout<<(n-m)*(mod+1)/2%mod<<endl;
}
return 0;
}
12
考虑将数 \(i\) 看做 \(2^i\),则每次 \(-1\) 操作相当于 \(/2\),每次分裂操作也相当于 \(/2\),所以只要满足存在一个 \(k\) 使得所有 \(2^x(x\leq k)\) 的和 \(\geq 4^k\) 即为 Alice 获胜。
Problem 12
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int a[1001000];
signed main()
{
int t;
scanf("%lld",&t);
while(t--)
{
int n;
scanf("%lld",&n);
for(int i=0;i<=n;i++)
scanf("%lld",a+i);
int x=1;
bool flag=0;
for(int i=0;i<=n;i++)
{
x-=a[i];
if(x<=0)
{
flag=1;
break;
}
x=min(100000000000000,x+x);
}
if(flag)
puts("Alice");
else puts("Bob");
}
return 0;
}

浙公网安备 33010602011771号