1. 程式人生 > 其它 >Codeforces Round #739 (Div. 3) 題解

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;
}