其他分享
首页 > 其他分享> > 8.21

8.21

作者:互联网

题面和题解

A.One

线性求解约瑟夫问题.

2种解法:

方法一

维护最后一个没有出局的人在每一轮的编号.

假设一个没有出局的人上一轮的编号为id,上一轮出局的人的编号为x,那么分以下两种情况:

  1. id>x,那么id-x>0,编号为id-x;
  2. 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;
}
*/
方法二

维护当前局数1的人的位置.

具体思路就是拆环成链,把每一轮出局的人排序,最后一个出局的人在最后(实际上不需要拆环,只是为了方便理解).

先从最后一轮开始,每次往上一轮递推.由于上一轮比这一轮会多一个人,我们令当前局人数tot++,数1的人now=now+1-i,由于可能会减多(因为上一轮的人数比这一轮多1),所以让i%tot,保证为上一轮人的编号而不会越编号的界.

最后第一个数1的人是now,由于规定了最后一个出局的人在最后,所以他开始的编号就是n-now+1.

点击查看代码
#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,now,tot;
int main()
{
	t=read();
	while(t--)
	{
		n=read();now=1,tot=1;
		for(rll i=n-1;i;i--)
		{
			tot++;now=now+1-i%tot;
			if(now<=0) now+=tot;
		}
		write(n-now+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;
}

标签:rt,rll,ch,ll,rg,8.21,define
来源: https://www.cnblogs.com/1Liu/p/16600166.html