联赛模拟11题解
好久没写博客了,模拟赛、联考也进行了好多,从今天开始总结。
T1 One
Solution
1种是网上的线性解法,将其编号0~n-1,从后往前推,ans最后一轮为0,每次(ans+=n-i+1)%=i,即加上这一轮应该死的人的报号再模上一轮的人数
还有一种是求出每轮某人死的时候他排在第几位(在上一轮剩下的人里),比如12345,3死了,排第三位,第二次4死了,他也排第3位。
最后一个剩下的肯定排第一位(only one left),然后看看前面死了的人有谁位置比他靠前,有就++(可能好理解一些)
// solutione_1
#include <cstdio>
#define rint register int
const int maxn=1e7+5;
int n,ans,cs;
int main(){
//freopen("1.in","r",stdin);
freopen("one.in","r",stdin);
freopen("one.out","w",stdout);
scanf("%d",&cs);
while(cs--){
scanf("%d",&n); ans=0;
for(rint i=2;i<=n;++i) (ans+=n-i+1)%=i;
printf("%d\n",ans+1);
}
return 0;
}
#include <cstdio>
#define rint register int
const int maxn=1e7+5;
int p[maxn],n,ans;
int main(){
//freopen("1.in","r",stdin);
freopen("one.in","r",stdin);
freopen("one.out","w",stdout);
rint cs; scanf("%d",&cs);
while(cs--){
scanf("%d",&n);
p[1]=1;
for(rint i=2;i<n;++i){
p[i]=(p[i-1]-2+i)%(n-i+1)+1;
/* p[i]=(p[i-1]-1+i)%(n-(i-1));
if(!p[i]) p[i]=(n-(i-1));
*/
}
ans=1;
for(rint i=n-1;i>=1;--i) if(p[i]<=ans) ans++;
printf("%d\n",ans);
}
return 0;
}
T2 砖块
Solution
小模拟,没啥好说的
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define rint register int
using namespace std;
const int maxn=1e2+5,INF=0x3f3f3f3f;
int k,op,tot,ans,x[maxn][15],y[maxn][15],mp[2000+1][2000+1];
char s[maxn];
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
freopen("block.in","r",stdin);
freopen("block.out","w",stdout);
int cs;scanf("%d",&cs);
while(cs--){
scanf("%d%s",&k,s+1);
tot=strlen(s+1);
for(rint i=1;i<=tot;++i){
for(rint j=1;j<=k;++j){
x[i][j]=-INF;
y[i][j]=-INF;
}
}
memset(mp,0,sizeof mp);
mp[1000][1000]=ans=1;
op=1;
for(rint i=1;i<=tot;++i){
if(op==1){
if(s[i]=='N'){
for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1],y[i][j]=y[i-1][1]+j;
}
else if(s[i]=='S'){
for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1],y[i][j]=y[i-1][1]-j;
}
else if(s[i]=='W'){
for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1]-j,y[i][j]=y[i-1][1];
}
else if(s[i]=='E'){
for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1]+j,y[i][j]=y[i-1][1];
}
for(rint j=1;j<=k;++j) ans=max(ans,++mp[1000+x[i][j]][1000+y[i][j]]);
op=2;
}
else{
if(y[i-1][1]==y[i-1][2]){
if(s[i]=='N'){
for(rint j=1;j<=k;++j) x[i][j]=x[i-1][j],y[i][j]=y[i-1][j]+1;
}
else if(s[i]=='S'){
for(rint j=1;j<=k;++j) x[i][j]=x[i-1][j],y[i][j]=y[i-1][j]-1;
}
else if(s[i]=='W'){
rint lefx=INF;
for(rint j=1;j<=k;++j) lefx=min(lefx,x[i-1][j]);
y[i][1]=y[i-1][1];
x[i][1]=lefx-1;
op=1;
}
else if(s[i]=='E'){
rint rigx=-INF;
for(rint j=1;j<=k;++j) rigx=max(rigx,x[i-1][j]);
y[i][1]=y[i-1][1];
x[i][1]=rigx+1;
op=1;
}
if(op==1) ans=max(ans,++mp[1000+x[i][1]][1000+y[i][1]]);
else for(rint j=1;j<=k;++j) ans=max(ans,++mp[1000+x[i][j]][1000+y[i][j]]);
}
else{
if(s[i]=='N'){
rint uy=-INF;
for(rint j=1;j<=k;++j) uy=max(uy,y[i-1][j]);
x[i][1]=x[i-1][1];
y[i][1]=uy+1;
op=1;
}
else if(s[i]=='S'){
rint dy=INF;
for(rint j=1;j<=k;++j) dy=min(dy,y[i-1][j]);
x[i][1]=x[i-1][1];
y[i][1]=dy-1;
op=1;
}
else if(s[i]=='W'){
for(rint j=1;j<=k;++j) y[i][j]=y[i-1][j],x[i][j]=x[i-1][j]-1;
}
else if(s[i]=='E'){
for(rint j=1;j<=k;++j) y[i][j]=y[i-1][j],x[i][j]=x[i-1][j]+1;
}
if(op==1) ans=max(ans,++mp[1000+x[i][1]][1000+y[i][1]]);
else for(rint j=1;j<=k;++j) ans=max(ans,++mp[1000+x[i][j]][1000+y[i][j]]);
}
}
}
if(op==1) printf("%d\n%d\n%d\n",x[tot][1],y[tot][1],ans);
else{
sort(x[tot]+1,x[tot]+1+k);
sort(y[tot]+1,y[tot]+1+k);
printf("%d",x[tot][1]);
for(rint i=2;i<=k;++i) printf(" %d",x[tot][i]);
printf("\n%d",y[tot][1]);
for(rint i=2;i<=k;++i) printf(" %d",y[tot][i]);
printf("\n%d\n",ans);
}
}
return 0;
}
T3 数字
等我搞完exLucas再说
T4
Solution
考场上想到了哈希,但带乘带加的线段树没调出来,只能交了一个\(n^2\)的暴力,不过2个循环就跑了70......数据不强
但还是挺可惜的。
对于甜圈,只有唯一的合法操作序列,我们将这个序列做一下字符串哈希。
然后对于每次修改,区间乘base,加区间加val,最后查询多少数的hash值符合要求即可
Code
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cmath>
#include <cctype>
#define rint register int
#define L (rt*2)
#define R (rt*2+1)
char buf[1<<20],*p1,*p2;
#define gc() (p1==p2?(p2=buf+fread(p1=buf,1,1<<20,stdin),p1==p2?EOF:*p1++):*p1++)
#define read() ({\
rint x=0; register bool f=0; register char ch=gc();\
while(!isdigit(ch)) f|=ch=='-',ch=gc();\
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch&15),ch=gc();\
f?-x:x;\
})
using namespace std;
typedef unsigned long long ull;
const int maxn=2e5+5;
const ull bs=13331;
int n,k,t,ans,l[maxn],r[maxn],d[maxn];
ull val[maxn],st;
bool pd=1;
ull w[maxn*4],lj[maxn*4],lc[maxn*4];
void down(rint rt,rint l,rint r,rint mid){
w[L]=w[L]*lc[rt]+lj[rt];
w[R]=w[R]*lc[rt]+lj[rt];
lj[L]=lj[L]*lc[rt]+lj[rt];
lj[R]=lj[R]*lc[rt]+lj[rt];
lc[L]*=lc[rt];
lc[R]*=lc[rt];
lj[rt]=0;lc[rt]=1;
}
void B(rint rt,rint l,rint r){
lc[rt]=1;
if(l==r) return;
rint mid=(l+r)/2;
B(L,l,mid);
B(R,mid+1,r);
}
void modify(rint rt,rint l,rint r,rint a,rint b,ull x){
if(a<=l&&r<=b){
lj[rt]=lj[rt]*bs+x;
lc[rt]*=bs;
w[rt]=w[rt]*bs+x;
return;
}
rint mid=(l+r)/2;
down(rt,l,r,mid);
if(a<=mid) modify(L,l,mid,a,b,x);
if(b >mid) modify(R,mid+1,r,a,b,x);
}
void query(rint rt,rint l,rint r){
if(l==r) return ans+=(w[rt]==st),void();
rint mid=(l+r)/2;
down(rt,l,r,mid);
query(L,l,mid),query(R,mid+1,r);
}
int main(){
freopen("deco.in","r",stdin);
freopen("deco.out","w",stdout);
n=read(),k=read(),t=read();
for(rint i=1;i<=k;++i) st=st*bs+i;
B(1,1,n);
for(rint i=1;i<=t;++i){
const rint l=read(),r=read(),d=read();
modify(1,1,n,l,r,d);
}
query(1,1,n);
printf("%d\n",ans);
return 0;
}