[cf] Codeforces Round #785 (Div. 2) A-C

目录

前言

传送门 :
阅读理解能力有待提高

A.

题意 :
给定一个字符串, A l i c e Alice Alice B o b Bob Bob分别操作, A l i c e Alice Alice先手询问是谁获胜并且输出得分

A l i c e : Alice : Alice:能拿长度为偶数的子串
B o b : Bob: Bob:能拿奇数的子串
得 分 : 得分: : a = 1 , b = 2..... a=1,b=2..... a=1,b=2.....

思路 :

  • 如果本串本来就是偶数,那么必然全拿
  • 否则只让 B o b Bob Bob拿首或者尾两者之中的最小一个

第二种情况,因为题中说明不存在平手,因此必然成立,因为最坏情况 : s [ 0 ] = = s [ s . s i z e ( ) − 1 ] s[0]==s[s.size()-1] s[0]==s[s.size()1]但是因为不存在平手,也可以分出胜负
Code :

void solve(){
	string s;cin>>s;
	if(s.size() == 1){
		cout<<"Bob"<<" "<<s[0]-'a'+1<<endl;
		return;
	}
	
	int sum = 0 ;
	for(auto x : s){
		sum+=x-'a'+1;
	}
	
	//全拿
	if(s.size()%2 == 0){
		cout<<"Alice "<<sum<<endl;
		return;
	}

	
	
	int minn = min(s[0],s[s.size()-1]);
	minn = minn-'a'+1;
	
	if(minn > sum - minn){
		cout<<"Bob "<<minn - (sum - minn)<<endl;
		return;
	}
	cout<<"Alice "<<sum-minn - minn <<endl;
	
}

B.

题意 :
给定一个字符串,对于任意一个三元组 ( t , u , v ) , t ∈ ( s 1 , s 2 , s 3.. ) , ( u , v ) ∈ s   ∣ c n t u − c n t v ∣ < = 1 (t,u,v),t\in(s1,s2,s3..),(u,v)\in s \ |cnt_u - cnt_v |<=1 (t,u,v),t(s1,s2,s3..),(u,v)s cntucntv<=1

即对于字符串的任意子串,都要满足字符串中任意两个字符,在该子串中的数量之差小于 1 1 1

思路 :
观察样例,我们可以知道,对于 a b a aba aba, a b c abc abc, a a a a a aaaaa aaaaa是成立的,同理我们再推几组 a b c a b c a ( 成 立 ) , a b b a b b a ( 不 成 立 ) abcabca(成立),abbabba(不成立) abcabca(),abbabba()

然后我们就会发现,两个连续之间要出现其他的所有字符,而连续的后面需要出现与前面相同的字符即构成一种
s [ 1 ] , s [ 2 ] , s [ 3 ] , s [ 1 ] , s [ 2 ] . . . . . s[1],s[2],s[3],s[1],s[2]..... s[1],s[2],s[3],s[1],s[2].....这种类型

显然的,这是可以证明是正确的,因为对于 s [ 1 ] , s [ 2 ] , s [ 3 ] s[1],s[2],s[3] s[1],s[2],s[3]必然是满足条件的,而对于 s [ 1 ] , s [ 2 ] , s [ 3 ] , s [ 1 ] s[1],s[2],s[3],s[1] s[1],s[2],s[3],s[1]也是满足的,同理下去归纳一下,显然就是了

因此我们只需要找到前面单个出现的,然后判断 s [ i ] = = s [ i − p o s ] s[i] == s[i-pos] s[i]==s[ipos]即可

Code :

void solve(){
	mp.clear();
	
	string s;cin>>s;
	int len  = s.size();
	
	int pos = 0;
	for(auto x : s){
		if(mp[x])break;
		pos++;
		mp[x] = 1;
	}
	
	for(int i=pos;i<len;i++){
		if(s[i]!=s[i-pos]){
			cout<<"NO"<<endl;
			return;
		}
	}
	
	cout<<"YES"<<endl;
	
	
}

C.

题意 :
给定一个数,对其进行拆分,询问有多少种方法,但是要拆分成回文数的相加

(一开始我还以为这个回文数值的是被拆分出来之后如果存在 1 , 3 , 1   , 1 , 1 , 3 1,3,1\ ,1,1,3 1,3,1 ,1,1,3就是回文什么的,结果只是简单的回文

思路 :
因此显然是一个原题,900. 整数划分,我们可以通过完全背包将一个数拆分成 1.. n 1..n 1..n的和并且求其方案数,但是必须是回文,因此我们考虑先暴力求出所有回文,求出来只有 499 499 499个,因此是可行的,然后套一下板子即可了

Code :

// Problem: Palindrome Basis
// Contest: Codeforces
// URL: https://m1.codeforces.com/contest/1673/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <iostream>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define IOS  ios::sync_with_stdio(false);
#define CIT  cin.tie(0);
#define COT  cout.tie(0);

#define ll long long
#define x first
#define y second
#define pb push_back
#define endl '\n'
#define all(x) (x).begin(),x.end()
#define Fup(i,a,b) for(int i=a;i<=b;i++)
#define Fde(i,a,b) for(int i=a;i>=b;i--)

typedef priority_queue<int,vector<int>,greater<int>>  Pri_m;
typedef pair<int,int> pii;
typedef vector<int> VI;
map<int,int> mp;
const int N = 4e4+10,mod = 1e9+7;
ll f[N];
int hw[N],idx;

bool check(int x){
	int tt[6] = {0};
	
	int cnt = 0 ;
	
	while(x){
		tt[++cnt]  = x%10;
		x/=10;
	}
	for(int i=1, j = cnt; i<=j;i ++ , j -- ){
		if(tt[i]!=tt[j])return false;
	}
	return true;
}
void init(){
	for(int i=1;i<=9;i++) hw[++idx]  = i;
	
	for(int i=10;i<=N;i++){
		if(check(i)) hw[++idx]  = i ;
	}
}
void solve_init(){
	// int n;cin>>n;
	
	// for(int i=1;i<=n;i++) f[i] = 0 ;
	
	f[0] = 1;
	
	for(int i=1;i<=idx;i++){
		for(int j=hw[i];j<=N;j++){
			f[j] = (f[j]%mod + f[j-hw[i]]%mod)%mod;
		}
	}
	// cout<<f[n]%mod<<endl;
}

void solve(){
	int n;cin>>n;
	cout<<f[n]%mod<<endl;
}
int main(){
	IOS
	CIT
	COT
	init();
	solve_init();
	
	// cout<<idx<<endl;
	
    int t;cin>>t;while(t--)
    solve();
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值