Pbri

Codeforces Round #739 (Div. 3) 题解

Codeforces Round #739 (Div. 3) 题解

A

模拟,用的时候拿就好。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T,a[MAXN],cnt;
int main(){
	FUP(i,1,1666)
	{
		if(i%3==0||i%10==3) continue;
		a[++cnt]=i;
	}
	T=read();
	while(T--) printf("%d\n",a[read()]);
	return 0;
}

B

用前两个数就能确定有多少个数,先判断有没有出界,没有的话直接加上一半然后取模就好了。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T,a,b,c;
void solve()
{
	a=read(),b=read(),c=read();
	if(a<b) swap(a,b);
	int n=(a-b)*2;
	if(a>n||b>n||c>n)
	{
		puts("-1");
		return;
	}
	printf("%d\n",(c+n/2-1)%n+1);
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

C

先确定在哪一圈,然后算。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
ll n;
void solve()
{
	n=read();
	ll lev=(int)(sqrt(n-1));
	if(n-lev*lev<=lev+1) printf("%lld %lld\n",n-lev*lev,lev+1);
	else printf("%lld %lld\n",lev+1,(lev+1)*(lev+1)-n+1);
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

D

考虑枚举最后变成了哪个数,将原数和二的幂都转换成字符串,设二的幂那个串为 \(S\) ,则原数是 \(T\) 。那么 \(S\) 的每一位要在 \(T\) 中依次出现,所以直接按顺序去匹配。 \(S\) 剩下的直接加上,多出来的减去,然后对所有答案取 \(\min\) 即可。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
char s[30];
char two[63][20]={"1","2","4","8","16","32","64","128","256","512","1024","2048","4096","8192","16384","32768","65536","131072","262144","524288","1048576","2097152","4194304","8388608","16777216","33554432","67108864","134217728","268435456","536870912","1073741824","2147483648","4294967296","8589934592","17179869184","34359738368","68719476736","137438953472","274877906944","549755813888","1099511627776","2199023255552","4398046511104","8796093022208","17592186044416","35184372088832","70368744177664","140737488355328","281474976710656","562949953421312","1125899906842624","2251799813685248","4503599627370496","9007199254740992","18014398509481984","36028797018963968","72057594037927936","144115188075855872","288230376151711744","576460752303423488","1152921504606846976","2305843009213693952","4611686018427387904"};
void solve()
{
	scanf("%s",s);
	int n=strlen(s),ans=INF;
	FUP(i,0,62)
	{
		int re=0,p1=0,p2=0;
		//printf("s=%s ",two[i]);
		while(p1<n&&p2<(int)strlen(two[i]))
		{
			if(s[p1]==two[i][p2]) p1++,p2++;
			else p1++;
		}
		re=n-p2;
		//printf("re=%d p1=%d p2=%d\n",re,p1,p2);
		if(p2<(int)strlen(two[i])) re+=strlen(two[i])-p2;
		ans=min(ans,re);
	}
	printf("%d\n",ans);
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

E

字符的种类数决定了分成多少段,字符最后出现的位置决定了他是在哪一段删去的(越往后出现那么越往后被删)。然后你知道这些之后就可以知道每一段每个字符出现了多少次(如果没删这个字符那么下个段的这个字符的数量不变),然后你对每一段跟上一段进行匹配,如果上一段的字符是删掉的就忽略这个字符(现在这一段的那个枚举的指针不变),然后如果枚举到了一个没删掉的字符又不是自己,那么肯定无解。然后你把第一段输出出去,然后再把那个顺序输出出去就好了。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 500010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
struct node{
	char c;
	int sum,num;
}p[27];
bool vis[27];
int cnt,n,id[27],tot[27],squ[27];
char s[MAXN];
void solve()
{
	memset(p,0,sizeof(p));
	memset(vis,0,sizeof(vis));
	memset(id,0,sizeof(id));
	memset(tot,0,sizeof(tot));
	memset(squ,0,sizeof(squ));
	cnt=0;
	scanf("%s",s+1);
	n=strlen(s+1);
	FDW(i,n,1)
	{
		if(!vis[s[i]-'a'])
		{
			vis[s[i]-'a']=true;
			p[++cnt].c=s[i],id[s[i]-'a']=cnt;
		}
		p[id[s[i]-'a']].sum++;
	}
	for(int x=1,y=cnt;x<y;x++,y--) swap(p[x],p[y]);
	FUP(i,1,cnt)
	{
		id[p[i].c-'a']=i;
		if(p[i].sum%i!=0)
		{
			puts("-1");
			return;
		}
		p[i].num=p[i].sum/i;
		//printf("p :%c %d %d\n",p[i].c,p[i].sum,p[i].num);
	}
	FUP(i,1,cnt)
	{
		FUP(j,i,cnt) squ[i]+=p[j].num;
		squ[i]+=squ[i-1];
	}
	//FUP(i,0,25) printf("%d ",id[i]);
	//puts("");
	FUP(i,2,cnt)
	{
		int p1=squ[i-1]+1,p2=squ[i-2]+1;
		for(;p1<=squ[i];p1++)
		{
			while(s[p2]==p[i-1].c&&p2<=squ[i-1]) p2++;
			if(p2>squ[i-1]||s[p2]!=s[p1])
			{
				puts("-1");
				return;
			}
			p2++;
		}
	}
	FUP(i,1,squ[1]) putchar(s[i]);
	putchar(' ');
	FUP(i,1,cnt) putchar(p[i].c);
	puts("");
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

F

考虑先判断自己是否符合要求,如果符合直接输出。然后再判断是否需要进位,进位之后的数如果 \(K=1\) 那么就是 \(1111.\).. ,否则是 \(1000...\) 。然后考虑枚举有多少个前缀相同,然后设目前的前缀有 \(cnt\) 个不同的数字,那么留自己以及后面发挥的 \(res=K-cnt\) ,然后考虑如果 \(res=0\) ,那么如果答案这一位比原数要大,那么这里只能是之前出现过的数中比原数这一位要大的最小的那个数,后面的数就填出现过的最小的数。如果 \(res>0\) 那么用类似的思路,填比这一位要大 \(1\) 的那个数,然后看看后面能不能填 \(0\) 一类的,类似的思路。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
ll change(char *s)
{
	ll ret=0;
	int len=strlen(s+1);
	FUP(i,1,len) ret=ret*10+s[i]-'0';
	return ret;
}
int T,K,n,cnt;
ll ans;
char s[20],tmp[20];
bool vis[10];
bool ck()
{
	FUP(i,1,n)
	{
		if(!vis[s[i]-'0'])
		{
			vis[s[i]-'0']=true;
			cnt++;
		}
	}
	return cnt<=K;
}
void solve()
{
	memset(tmp,0,sizeof(tmp));
	memset(vis,0,sizeof(vis));
	cnt=0;
	ans=LLINF;
	scanf("%s%d",s+1,&K);
	n=strlen(s+1);
	if(ck())
	{
		printf("%s\n",s+1);
		return;
	}
	memset(tmp,0,sizeof(tmp));
	memset(vis,0,sizeof(vis));
	cnt=0;
	if(K==1) FUP(i,1,n+1) tmp[i]='1';
	else
	{
		tmp[1]='1';
		FUP(i,2,n+1) tmp[i]='0';
	}
	ans=change(tmp);
	memset(tmp,0,sizeof(tmp));
	FUP(i,1,n)
	{
		if(i>1)
		{
			tmp[i-1]=s[i-1];
			if(!vis[s[i-1]-'0']) vis[s[i-1]-'0']=true,cnt++;
		}
		int res=K-cnt;
		if(res<0) break;
		if(s[i]=='9') continue;
		if(res==0)
		{
			//printf("i=%d\n",i);
			int p=-1;
			FUP(j,s[i]-'0'+1,9)
			{
				if(vis[j])
				{
					p=j;
					break;
				}
			}
			if(p==-1)
			{
				if(vis[s[i]-'0'])
				{
					tmp[i]=s[i];
					continue;
				}
				else break;
			}
			tmp[i]=p+'0';
			p=-1;
			FUP(j,0,9)
			{
				if(vis[j])
				{
					p=j;
					break;
				}
			}
			FUP(j,i+1,n) tmp[j]=p+'0';
			ans=min(ans,change(tmp));
			if(!vis[s[i]-'0']) vis[s[i]-'0']=true,cnt++;
		}
		else
		{
			//printf("res>0 i=%d\n",i);
			tmp[i]=s[i]+1;
			if(!vis[tmp[i]-'0']) res--;
			if(res||vis[0]||i==n)
			{
				//puts("111");
				//printf("tmp=%s n=%d\n",tmp+1,n);
				FUP(j,i+1,n) tmp[j]='0';
				ans=min(ans,change(tmp));
			}
			else
			{
				//puts("# 111");
				int p=-1;
				FUP(j,0,9)
				{
					if(vis[j]||j==s[i]+1-'0')
					{
						p=j;
						break;
					}
				}
				FUP(j,i+1,n) tmp[j]=p+'0';
				//printf("tmp=%s\n",tmp+1);
				ans=min(ans,change(tmp));
			}
			if(!vis[s[i]-'0']) vis[s[i]-'0']=true,cnt++;
			tmp[i]=s[i];
		}
	}
	printf("%lld\n",ans);
}
int main(){
	T=read();
	while(T--) solve(); 
	return 0;
}
posted @ 2021-08-19 12:09  Pbri  阅读(58)  评论(0编辑  收藏  举报