Codeforces Round #293 (Div. 2) (A B C D E)

本文详细解析了Codeforces Round #293 Division 2的比赛题目,包括字符串比较、字母统计、智能手机应用模拟、概率DP和贪心策略解题。A题关注字符串大小比较,B题涉及字母频率统计,C题需要模拟应用安装顺序,D题通过动态规划解决扶梯问题,E题用贪心算法处理连续问号的约束问题。

Vitaly and Strings

        题目已经保证s比t小了,那么只需要将s增加1(看成26进制数),然后比较是否相等即可。我居然跪了2发。

#include <bits/stdc++.h>  
using namespace std;   

char s[110];
char t[110];

int main(){
	scanf("%s",s);
	scanf("%s",t);
	
	int len=strlen(s);
	
	s[len-1]++;
	int i=len;
	while(i--){
		if(s[i]>'z'){
			s[i]='a';
			s[i-1]++;
		}else{
			break;
		}
	}
	
	if(i==-1||strcmp(s,t)==0){
		printf("No such string");
	}else{
		printf("%s",s);
	}
	
	
	return 0;
}

Tanya and Postcard

        统计每个字母有几个,扫两遍,第一遍满足完全一样的,第二遍满足大小写不符的。

#include <bits/stdc++.h>  
using namespace std;   

const int maxn=200010;

char s[maxn];
char t[maxn];

int cnt[200];

int main(){
	scanf("%s",s);
	scanf("%s",t);
	
	int lens=strlen(s);
	int lent=strlen(t);
	
	for(int i=0;i<lent;i++){
		cnt[t[i]]++;
	}
	
	int ans1=0;
	int ans2=0;
	
	for(int i=0;i<lens;i++){
		if(cnt[s[i]]){
			cnt[s[i]]--;
			ans1++;
			s[i]=0;
		}
	}
	
	for(int i=0;i<lens;i++){
		if(s[i]){
			if(s[i]<'a'){
				if(cnt[s[i]+32]){
					cnt[s[i]+32]--;
					ans2++;
				}
			}else{
				if(cnt[s[i]-32]){
					cnt[s[i]-32]--;
					ans2++;
				}
			}
		}
	}
	cout<<ans1<<" "<<ans2<<endl;
	return 0;
}

Anya and Smartphone

        直接模拟即可,记录第几个位置是第几个应用和第几个应用在第几个位置。

#include <bits/stdc++.h>  
using namespace std;   

const int maxn=100010;

int a[maxn];
int _a[maxn];

int main(){
	int n,m,k;
	cin>>n>>m>>k;
	
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		_a[a[i]]=i;
	}
	
	long long ans=0;
	for(int i=1;i<=m;i++){
		int b;
		scanf("%d",&b);
		int t=_a[b];
		ans+=((_a[b]-1)/k+1);
		if(t>1){
			swap(_a[b],_a[a[t-1]]);
			swap(a[t],a[t-1]);
		}
	}
	cout<<ans<<endl;
	return 0;
}

Ilya and Escalator

        特别水的概率dp。dp(i,j)表示第i秒里面有j人。每个状态由两种状态转移而来,上一秒进来人和没有进来人。

#include <bits/stdc++.h>  
using namespace std;   

const int maxn=100010;

double dp[2010][2010];

int main(){
	int n,t;
	double p;
	cin>>n>>p>>t;
	
	dp[0][0]=1.0;
	
	for(int i=1;i<=t;i++){
		for(int j=0;j<=n;j++){
			if(j)dp[i][j]+=dp[i-1][j-1]*p;
			if(j!=n) dp[i][j]+=dp[i-1][j]*(1.0-p);
			else dp[i][j]+=dp[i-1][j];
		}
	}
	
	double ans=0.0;
	for(int i=1;i<=n;i++){
		ans+=dp[t][i]*i;
	}
	
	printf("%.8lf\n",ans);
	
	return 0;
}

Arthur and Questions

        第一眼看上去像差分约束,其实就是贪心。很容易推出只要保证所有ai<ai+k即可。把这些数分为1~k组,每一组是独立的,一组一组处理连续的'?',方法是贪心使得所有问号的绝对值之和尽量小(优先让连续'?'中最中间的等于0,如果不行就按制约条件修改值)。具体见代码。

#include <bits/stdc++.h>  
using namespace std;   

int a[100010];
const int INF=1e9+1e5+7;

int get_first(int MIN,int MAX,int len){
	int re=max(-(len-1)/2,MIN);	//优先让最中间为0,受最左边制约 
	re=min(re,MAX-len+1);		//受最右边制约 
	return re;
}

int main(){
	int n,k;
	cin>>n>>k;
	
	for(int i=1;i<=n;i++){
		char tmp[16];
		scanf("%s",tmp);
		if(tmp[0]=='?'){
			a[i]=INF;			//把问号暂时置为INF 
		}else{
			a[i]=atoi(tmp);
		}
	}
	
	for(int i=1;i<=k;i++){
		int s=i+k;
		int t=0;
		
		if(a[i]==INF){
			a[i]=-INF;
			if(i+k>n)a[i]=0;
			s=i;
			t=i;
		}
		
		int j=i+k;
		while(j<=n){
			if(a[j]==INF){	//问号 
				a[j]=a[j-k]+1;
				t=j;
				if(j+k>n){
					int tmp=get_first(a[s],INF,(t-s)/k+1);
					for(int l=s;l<=t;l+=k){
						a[l]=tmp++;
					}
				}
				
			}else{	//碰到了数字,处理之前的那一串? 
				int tmp=get_first(a[s],a[j]-1,(t-s)/k+1);

				for(int l=s;l<=t;l+=k){
					a[l]=tmp++;
				}
				s=j+k;
			}
			j+=k;
		}
	}
	
	
	bool ok=1;
	for(int i=1;i<=k;i++){
		int j=i+k;
		while(j<=n){
			if(a[j]<=a[j-k]){
				ok=0;
				break;
			}
			j+=k;
		}
	}
	
	if(ok){
		for(int i=1;i<=n;i++){
			printf("%d ",a[i]);
		}
		printf("\n");
	}else{
		printf("Incorrect sequence\n");
	}
	return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值