题面和题解
A.One
线性求解约瑟夫问题.
2种解法:
方法一
维护最后一个没有出局的人在每一轮的编号.
假设一个没有出局的人上一轮的编号为id,上一轮出局的人的编号为x,那么分以下两种情况:
- id>x,那么id-x>0,编号为id-x;
- id<x,那么id-x<0,设上一轮的总人数为tot,显然id-x+tot<tot,编号即为id-x+tot.
这两种情况可以合并吗?
当然可以.当id-x>0时,它加上任何一个数再模这个数是不变的;当id-x<0时,它模上这个数一定是不变的.所以合并后上一轮的编号即为:
.叙述成文字语言就是:
下一轮该人的编号=上一轮出局的人的编号+上一轮该人的编号.那么代码就好理解了.
点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
using namespace std;
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
ll t,n,ans;
int main()
{
t=read();
while(t--)
{
n=read();ans=0;
for(rll i=2;i<=n;i++) ans=(ans+n-i+1)%i;
//加n-i+1是因为上一轮有n-i+1个人
write(ans+1);puts("");
}
return 0;
}
/*标准约瑟夫环问题:
#include<stdio.h>
int main()
{
int n,m,i,s=0;
scanf("%d%d",&n,&m);
for(i=2;i<=n;i++)
s=(s+m)%i;
printf("%d",s+1);
return 0;
}
*/
B.砖块
小模拟,模拟每次翻转的情况,把覆盖坐标加入map或者数组即可.
点击查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
#define ll int
#define rg register
#define rll rg ll
#define maxn 201
#define base 15000
#define pll pair<ll,ll>
using namespace std;
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
ll t,n,len,ans;
ll zt,x,y;
// map<pll,short> mp;
__gnu_pbds::list_update<pll,short> mp; //O(n)复杂度的map,功能与map相同,需要#include<bits/extc++.h>库
char s[maxn];
int main()
{
t=read();
while(t--)
{
zt=x=y=ans=0;mp.clear();n=read();
mp[(pll) { 0,0 }]=1;
scanf("%s",s+1);len=strlen(s+1);
for(rll i=1;i<=len;i++)
{
switch(s[i])
{
case 'N':
if(!zt)
{
zt=1;y++;
for(rll i=y;i<y+n;i++)
mp[(pll) { x,i }]++,ans=max(ans,(ll)mp[(pll) { x,i }]);
}
else if(zt==1)
zt=0,y+=n,mp[(pll) { x,y }]++,ans=max(ans,(ll)mp[(pll) { x,y }]);
else
{
y++;
for(rll i=x;i<x+n;i++)
mp[(pll) { i,y }]++,ans=max(ans,(ll)mp[(pll) { i,y }]);
}
break;
case 'S':
if(!zt)
{
zt=1;y-=n;
for(rll i=y;i<y+n;i++)
mp[(pll) { x,i }]++,ans=max(ans,(ll)mp[(pll) { x,i }]);
}
else if(zt==1)
zt=0,y--,mp[(pll) { x,y }]++,ans=max(ans,(ll)mp[(pll) { x,y }]);
else
{
y--;
for(rll i=x;i<x+n;i++)
mp[(pll) { i,y }]++,ans=max(ans,(ll)mp[(pll) { i,y }]);
}
break;
case 'W':
if(!zt)
{
zt=2;x-=n;
for(rll i=x;i<x+n;i++)
mp[(pll) { i,y }]++,ans=max(ans,(ll)mp[(pll) { i,y }]);
}
else if(zt==1)
{
x--;
for(rll i=y;i<y+n;i++)
mp[(pll) { x,i }]++,ans=max(ans,(ll)mp[(pll) { x,i }]);
}
else
zt=0,x--,mp[(pll) { x,y }]++,ans=max(ans,(ll)mp[(pll) { x,y }]);
break;
case 'E':
if(!zt)
{
zt=2;x++;
for(rll i=x;i<x+n;i++)
mp[(pll) { i,y }]++,ans=max(ans,(ll)mp[(pll) { i,y }]);
}
else if(zt==1)
{
x++;
for(rll i=y;i<y+n;i++)
mp[(pll) { x,i }]++,ans=max(ans,(ll)mp[(pll) { x,i }]);
}
else
zt=0,x+=n,mp[(pll) { x,y }]++,ans=max(ans,(ll)mp[(pll) { x,y }]);
break;
}
}
if(!zt)
write(x),puts(""),write(y),puts("");
else if(zt==1)
{
for(rll i=1;i<=n;i++) write(x),putchar(' ');puts("");
for(rll i=y;i<=y+n-1;i++) write(i),putchar(' ');puts("");
}
else
{
for(rll i=x;i<x+n;i++) write(i),putchar(' ');puts("");
for(rll i=1;i<=n;i++) write(y),putchar(' ');puts("");
}
write(ans);puts("");
}
return 0;
}
C.数字
贺的,咕咕咕
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define maxn 201
#define base 10000
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
static inline void read(rg char x) { scanf("%c",&x); }
static inline void read(rg char* x) { scanf("%s",x); }
static inline void read(rg string x) { cin>>x; }
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|'0');
}
struct bigint
{
ll s[maxn],len;
inline void eq(rg char* ss)
{
memset(s,0,sizeof(s));rll l=strlen(ss);
len=(l-1>>2)+1;
for(rll i=1;i<len;i++) s[i]=(ss[l-(i<<2)]-'0')*1000+(ss[l-(i<<2)+1]-'0')*100+(ss[l-(i<<2)+2]-'0')*10+(ss[l-(i<<2)+3]-'0');
for(rll i=1;i<=(l-1)%4+1;i++) s[len]=s[len]*10+(ss[i-1]-'0');
}
inline friend bigint operator/(rg bigint a,rll b)
{
for(rll i=a.len;i;i--) a.s[i-1]+=a.s[i]%b*base,a.s[i]/=b;
while(a.len&&(!a.s[a.len])) a.len--;return a;
}
inline friend ll operator%(rg bigint a,rll b) { return a.s[1]%b; }
inline bool operator<=(rll b) { return len<=1&&s[1]<=b; }
}n,m;
ll mod[]={1,10,100,1000};
ll t,k,len,num,ans;
char s[maxn];
ll jc1[maxn],jc2[maxn];
static __inline ll ksm(rll a,rll b,rll mod) { rll ans=1; a%=mod; for(rll i=b;i;i>>=1) { if(i&1) ans=ans*a%mod; a=a*a%mod; }return ans; }
static __inline ll pre(rg bigint n)
{
if(n<=125) return jc1[n.s[1]];
rll x=n%125;n=n/5;rll k=pre(n);n=n/25;
return k*ksm(jc2[125],n%100,125)%125*jc2[x]%125;
}
void print(rll x,rll k)
{
for(rll i=k;i;i--)
if(!(x%mod[i]/mod[i-1])) putchar('0');
else break;
write(x%mod[k]);putn;
}
int main()
{
jc1[0]=jc2[0]=1;
for(rll i=1,t;i<=125;i++)
{
t=i;while(!(t%5)) t/=5;
jc1[i]=jc1[i-1]*t%125;jc2[i]=jc2[i-1]*((!(i%5))?1:i)%125;
}
t=read();
while(t--)
{
read(s);k=read();len=strlen(s);
n.eq(s);ans=pre(n);
if(len==1&&n.s[1]<=6)
{
rll t=1;for(rll i=1;i<=n.s[1];++i) t*=i;
if(t%10==0) t/=10;
print(t,k);continue;
}
m=n;num=0;
while(m.len) m=m/5,num=(num+m%100)%100;
ans=(ans*ksm(63,num,125))%125;
for(rll i=0;i<=999;i+=8) if(i%125==ans) print(i,k);
}
return 0;
}
D.甜圈
暴力一定会T,考虑用线段树.
既然维护每一次的操作和顺序太麻烦,那么可以考虑利用哈希可以保存顺序的特点,把每次操作当成字符串,将哈希加入线段树中,维护一个区间加和区间乘,最后check一下每个点的哈希是否与标准哈希(就是从1到k顺序操作计算出的哈希值)相等即可.
我不知道为什么哈希的base取7都可以过
点击查看代码
#include<bits/stdc++.h>
#ifndef ONLINE_JUDGE
#include<debug>
#endif
#define ll long long
#define rg register
#define rll rg ll
#define ull unsigned ll
#define maxn 200001
#define base 7
using namespace std;
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
struct tree
{
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
ull tag1,tag2;
ull v;
tree() { tag2=1; }
}t[maxn<<2];
ll n,k,len,T,l,r,x,ans;
ull h,stdh;
#define pushup(x) t[x].v=t[ls(x)].v+t[rs(x)].v
static inline void pushdown(rll rt,rll l,rll r)
{
rll mid=(l+r)>>1;
if(t[rt].tag2!=1)
{
t[ls(rt)].v*=t[rt].tag2;t[rs(rt)].v*=t[rt].tag2;
t[ls(rt)].tag1*=t[rt].tag2;t[rs(rt)].tag1*=t[rt].tag2;
t[ls(rt)].tag2*=t[rt].tag2;t[rs(rt)].tag2*=t[rt].tag2;
t[rt].tag2=1;
}
if(t[rt].tag1)
{
t[ls(rt)].v+=t[rt].tag1*(mid-l+1);
t[rs(rt)].v+=t[rt].tag1*(r-mid);
t[ls(rt)].tag1+=t[rt].tag1;
t[rs(rt)].tag1+=t[rt].tag1;
t[rt].tag1=0;
}
}
static inline void upd(rll rt,rll l,rll r,rll x,rll y,rg ull v)
{
if(x<=l&&r<=y) { t[rt].v=t[rt].v*base+v*(r-l+1); t[rt].tag1=t[rt].tag1*base+v; t[rt].tag2*=base; return; }
pushdown(rt,l,r);rll mid=(l+r)>>1;
if(x<=mid) upd(ls(rt),l,mid,x,y,v);if(y>mid) upd(rs(rt),mid+1,r,x,y,v);
pushup(rt);
}
static inline ull query(rll rt,rll l,rll r)
{
if(l==r) { return (t[rt].v==stdh); }
pushdown(rt,l,r);rll mid=(l+r)>>1;
return query(ls(rt),l,mid)+query(rs(rt),mid+1,r);
}
int main()
{
n=read();k=read();
for(rll i=1;i<=k;i++)
stdh=stdh*base+i;
T=read();
while(T--)
{
l=read();r=read();x=read();
upd(1,1,n,l,r,x);
}
write(query(1,1,n));
return 0;
}
当然数据范围是200000,用分块做更简单.只需要维护每个区间的上次操作即可.
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 200001
using namespace std;
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
ll t,n,k,len,l,r,x;
ll a[maxn],L[501],R[501],bel[maxn];
static inline void push(rll x)
{
if(L[x])
{
rll tl=(x-1)*len+1,tr=min(x*len,n);
for(rll i=tl;i<=tr;i++)
{
if(a[i]+1==L[x]) a[i]=R[x];
else a[i]=-1;
}
L[x]=R[x]=0;
}
}
static inline void upd(rll l,rll r,rll x)
{
for(rll i=l;i<=r;i++)
{
if(a[i]+1==x) a[i]++;
else a[i]=-1;
}
}
int main()
{
n=read();k=read();len=sqrt(n);
for(rll i=1;i<=n;++i) bel[i]=(i+len-1)/len;
t=read();
while(t--)
{
l=read();r=read();x=read();
push(bel[l]);push(bel[r]);
if(bel[l]==bel[r]) { upd(l,r,x);continue; }
upd(l,min(bel[l]*len,n),x);
upd((bel[r]-1)*len+1,r,x);
for(rll i=bel[l]+1;i<bel[r];i++)
{
if(L[i]!=-1)
{
if(!L[i]) L[i]=R[i]=x;
else
{
if(R[i]+1==x) R[i]++;
else L[i]=R[i]=-1;
}
}
}
}
for(rll i=1;i<=bel[n];i++) push(i);
rll ans=0;
for(rll i=1;i<=n;i++) if(a[i]==k) ans++;
write(ans);
return 0;
}