Educational Codeforces Round 57 (Rated for Div. 2)

https://codeforces.com/contest/1096

https://codeforces.com/contest/1096/problem/B

题解:

比如aacdeee
如果我们想保留左边的a 话 那么需要删除的是aa后面的所有,以及一个a, 连续的a 的长度为2  可删除的为 cdeee  acdeee 两种
如果想保留右边e的话 那么要删除的是右边aacd   然后 和两个e  一共三种删除方法。
所以左右不等于的时候 删除方法就很明显了 

第二种情况 eecdeee
左边连续2  右边连续3  
其实就可以这么理解 左边2个位置 右边 3个位置 左边选一个 右边选一个   和不保留左边或者字符的  2 + 3 种方法。
比如 删除 ecde    和删除 eecd  就是左边保留字符的删除方法和不保留字符的删除方法
 
#include <iostream>
#include <cstring>
using namespace std;
#define int long long
#define mod 998244353
signed main(){
    //cout << "Hello world!" << endl;
    int n;
    cin>>n;
    string s;
    cin>>s;
    int l=1;
    int r=1;
    for(int i=0;i<n;i++){/*左边最长长度*/
        if(s[i]==s[i+1])
            l++;
        else
            break;
    }
    for(int i=n-1;i>=0;i--){/*右边最长长度*/
        if(s[i]==s[i-1])
            r++;
        else
            break;
    }
    int ans=1;/*全删*/
    if(s[0]==s[n-1])/*左右相等话复杂一点,删除中间那一段也是一次,自己画画吧*/
        ans+=(r+l+r*l)%mod;/*   r*l  左右不用贴着删,但是至少要保留一个字符*/
    else/*左右不等很简单,自己模拟一遍*/
        ans+=(l+r)%mod;/*贴着左边依次往右扩展(r),贴着右边依次往左边扩展(l)*/
    cout<<ans<<endl;
    return 0;
}

https://codeforces.com/contest/1096/problem/C

题意:
给定一个角度 θθ,请你寻找一个正 nn 边型,满足在这个正 nn 边型上找三个顶点 A,B,CA,B,C (可以不相邻),使得 ∠ABC = θ∠ABC = θ 。请输出最小的 nn。保证 nn 不超过 998244353998244353。多组数据。

注意给出的 θθ 是使用角度制表示的。

题解:

数学公式了 
首先 n边形的一个内角度数为  
180-360/n   = (180 n -360) /n = 180*(n-2)/n  ;

然后  多边形的一个内角 可以被 等分为n-2 个  这点可以画图证明

设内角 大小  180*(n-2)/n =x; 需要查找的角度为y 
x/(n-2)  =  y /d    d为x/(n-2) 的倍数 
之后 公式化简   变成  180*d / y= n  
这里证明  180 *d  必须是y 的整数倍数
所以只需要求 180 和 y 的最小公倍数 然后除以 y  的结果就是 n的一个公约数 了
之后去让检查这个n是否符合内角的大小- - 然后循环
  比如  178 和 180  寻找到的n 是90   但是 实际上是180  
  原因就是 90 的内角是 176度  少于178° 。
  


#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
long long lcm(long long a,long long b)
{
    return a*b/gcd(a,b);
}
int main()
{
    long long t;
    cin>>t;
    while(t--)
    {
        long long ss;
        cin>>ss;
        long long lc=lcm(180,ss);
        int n=lc/ss,ns=lc/ss;
        int q=1;
        while(180*(n-2)/n<ss) n=ns*q++ ; //判断是否符合内角的大小
        cout<<n<<endl;
       // cout<<lc/n<<endl;
    }
}

https://codeforces.com/contest/1096/problem/D

题意:长度为n的字符串 删除每个位置的字符有花费 求使其没有hard的子序列的最小花费

题解:
四种字符只需要删除其中任意一种就可以保证无法构成hard  

四种字符的次序也是固定的  ,  所以 我们当碰到第一个时 才需要注意第二个  碰到第二个时,才需要注意第三个  
依次类推,
所以dp方程就是  
dp[x]=min(dp[x-1],dp[x]+a[i]);


#include <bits/stdc++.h>
using namespace std;
long long dp[100005],a[100005];
int main()
{
    long long n;
    while(cin>>n)
    {
        string s;
        cin>>s;
        memset(dp,0,sizeof(dp));
        for(long long i=0;i<n;i++) cin>>a[i];
        for(long long i=0; i<n; i++)
        {
            if(s[i]=='h')
            {
                dp[1]=dp[1]+a[i];
            }
            else if(s[i]=='a')
            {
                dp[2]=min(dp[1],dp[2]+a[i]);
            }
            else if(s[i]=='r')
            {
                dp[3]=min(dp[2],dp[3]+a[i]);
            }
            else if(s[i]=='d') dp[4]=min(dp[3],dp[4]+a[i]);
        }
        cout<<min( min(dp[1],dp[2]),min(dp[3],dp[4]) ) <<endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值