CF每日一练(1.17)

A - Find Divisible

CodeForces - 1096A

水题,直接输出 l 2*l 即可

B - Substring Removal

CodeForces - 1096B

记录左边有l个字母相同,右边有r个字母相同,肯定会有 r+l+1种,然后如果有s[1] == s[n],那么还可以移除中间的子串,要再加上l*r即可(因为题目保证有两个不同的字符)

#include <iostream>
#include <cstdio>
using namespace std;
const int mod = 998244353;
int n;
char s[200010];
int main()
{
	scanf("%d %s",&n,s);
	int l=1,r=1;
	for(;s[l-1]==s[l];l++);
	for(;s[n-r-1]==s[n-r];r++);
	long long ans = l+r+1;
	if(s[0] == s[n-1])
		ans = (ans+1ll*l*r)%mod;
	cout<<ans<<endl;
	return 0;
}

C - Polygon for the Angle

CodeForces - 1096C

题意:给一个角度ang(1<=ang<180) 然后输出如图所示规则的最小正n边形的边数

分析:abc三点构成一个三角形,而三角形内角的比例就对应于它们各自对应的那段边数比。如图,54度对应三份,剩下的分别对应五份和两份。

所以,对于任意一个角度ang,先求出g=gcd(ang,180),即每一边可以对应多少度,然后 n=180/g 即为正n边形的边数,wait wait!是不是有点太快了,别忘了我们的前提条件,我们是用三角形内角比例等于对应边数比得到的结论,我们要让它满足能够组成三角形这一条件,所以发现当 ang/180==(n-1)/n 时(想一想为什么是这样),就无法组成三角形(因为只剩下一份了,不够与ang组成三角形),这个时候只需将 n乘以2即可。

#include <bits/stdc++.h>
using namespace std;
int T,ang,n;
int main()
{
	cin>>T;
	while(T--)
	{
		cin >> ang;
		int n = 180/__gcd(ang,180);
		if(ang * n / 180 == n-1){
			n*=2;
		}
		cout << n << endl;
	}
}

D - Easy Problem

CodeForces - 1096D

题意:有一长度为n的字符串,每一字符都有一个权值,要求现在从中取出若干个字符,使得字符串中没有子串hard,(这里的子串在原串中不需要连续)。求取出字符的最小权值和。

分析:dp,

  • h的决策只能时消灭h
  • a的决策是将前面的h消灭,或者是以最优策略消灭前面顺序符合的 ha
  • 同理,r的策略是使用a的策略消灭ha,或者是以最优策略消灭har
  • d同理。

最后输出解决d的情况即可。因为d里面包含了前面所有的情况。

考虑到权值比较大,n为1e5,可能会爆int

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
const int inf = 0x3f3f3f3f;
string s;
long long  n,x;
long long h,a,r,d;
int main()
{
	cin>>n>>s;
	for(int i=0;i<n;i++)
	{
		cin>>x;
		if(s[i] == 'h')h+=x;
		else if(s[i]=='a') a = min(h,a+x);
		else if(s[i]=='r') r=min(a,r+x);
		else if(s[i]=='d') d=min(r,d+x);
	}
	cout<<d<<endl;
	return 0;
}
posted @ 2019-01-17 16:11  长安大学ACM  阅读(204)  评论(0编辑  收藏  举报