Codeforces Round #427 (Div. 2)

还差7分就蓝名了,加油!!!!

A. Key races

题目大意:有两个打字员,一共有s个字要打,第一个打字员打字速度为v1秒/字 ,延迟为t1,第二个打字员

打字速度为v2秒/字,延迟为t2。开始打字前和开始打字后都有一个延迟,问你谁快。

思路:水题,XJB搞搞就好。

#include<bits/stdc++.h>
using namespace std;
int s,v1,v2,t1,t2;
int main()
{
    cin>>s>>v1>>v2>>t1>>t2;
    int x=v1*s+2*t1;
    int y=v2*s+2*t2;
    //cout<<x<<endl;
    //cout<<y<<endl;
    if(x>y) puts("Second");
    else if(x<y) puts("First");
    else puts("Friendship");
    return 0;
}
View Code

B. The number on the board

题目大意:给你一串数字,要求每个数字相加要大于等于k,问你最少改变几个数字。

思路:先排序,如果不够优先用小的补。

#include<bits/stdc++.h>
using namespace std;
char s[100005];
int k;
int sum[100005];
int main()
{
    cin>>k;
    scanf("%s",s+1);
    int len=strlen(s+1);
    sort(s+1,s+len+1);
    int cnt=0;
    for(int i=1;i<=len;i++)
    {
        sum[i]=sum[i-1]+(s[i]-'0');
        cnt+=s[i]-'0';
    }
    if(cnt>=k)
    {
        puts("0");
        return 0;
    }
    int ans=0;
    for(int i=1;i<=len;i++)
    {
        ans++;
        if(cnt+9*i-sum[i]>=k) break;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

C. Star sky

题目大意:在100*100的网格中,中n个星星,每个星星的初始亮度为s[ i ],且所有星星的最大亮度为c(c<=10),每过一秒

所有星星亮度加1,亮度为c的变成0。有q个询问,每个询问给你一个矩形,问在 t 秒的时候这里面所有星星的亮度总和为多少。

思路:考虑到c<=10比较小,我们可以开一个dp[ 101 ][ 101 ][ 11 ], dp[ i ][ j ][ k ] 表示以( i , j )为右上顶点,( 0 , 0)为左下顶点

的矩形中亮度为k的星星有多少个。 这样在询问中我们就能O(1)进行查询了。

#include<bits/stdc++.h>
using namespace std;
int n,q,c,mp[105][105][11],dp[105][105][11];
int main()
{
    scanf("%d%d%d",&n,&q,&c);
    for(int i=1;i<=n;i++)
    {
        int x,y,s;
        scanf("%d%d%d",&x,&y,&s);
        mp[x][y][s]++;
    }
    for(int i=1;i<=100;i++)
    {
        for(int j=1;j<=100;j++)
        {
            for(int k=0;k<=10;k++)
            {
                dp[i][j][k]=mp[i][j][k];
                if(i==1 && j==1) continue;
                if(j==1) dp[i][j][k]+=dp[i-1][j][k];
                else if(i==1) dp[i][j][k]+=dp[i][j-1][k];
                else
                {
                    dp[i][j][k]+=dp[i-1][j][k]+dp[i][j-1][k];
                    dp[i][j][k]-=dp[i-1][j-1][k];
                }
            }
        }
    }
    while(q--)
    {
        int sum=0;
        int x1,y1,x2,y2,t;
        scanf("%d%d%d%d%d",&t,&x1,&y1,&x2,&y2);
        for(int i=0;i<=10;i++)
        {
            int cnt=0;
            cnt=dp[x2][y2][i]+dp[x1-1][y1-1][i]-dp[x1-1][y2][i]-dp[x2][y1-1][i];
            sum+=cnt*((i+t)%(c+1));
        }
        printf("%d
",sum);
    }
    return 0;
}
View Code

 D. Palindromic characteristics

题目大意:给你一个字符串,让你找各个k-回文串的数量,定义:1-回文串为普通回文串,k-回文串为 这个回文串的前一部分和

后一部分都为(k-1)-回文串。

思路:其实只要会dp求回文串的数量这个就好写了,然后我比赛的时候忘了怎么用dp求回文串就GG了,复杂度O( n ^ 2 ),好像

还有更简单的O( n * logn )的方法。

#include<bits/stdc++.h>
using namespace std;
int ans[5005],dp[5005][5005];
char s[5005];
int main()
{
    scanf("%s",s);
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        dp[i][i]=1;
        if(i!=len-1 && s[i]==s[i+1])
        {
            dp[i][i+1]=2;
            ans[2]++;
        }
    }
    ans[1]+=len;
    for(int k=3;k<=len;k++)
    {
        for(int i=0;i+k-1<len;i++)
        {
            int j=i+k-1;
            if(s[i]==s[j] && dp[i+1][j-1])
            {
                int m=(i+j)>>1;
                if((i+j)%2)
                {
                    dp[i][j]=min(dp[i][m],dp[m+1][j])+1;
                    ans[dp[i][j]]++;
                }
                else
                {
                    dp[i][j]=min(dp[i][m-1],dp[m+1][j])+1;
                    ans[dp[i][j]]++;
                }
            }
        }
    }
    for(int i=len-1;i>=1;i--) ans[i]+=ans[i+1];
    for(int i=1;i<=len;i++) printf("%d%c",ans[i],i==len?'
':' ');
    return 0;
}
View Code

ps:

顺便贴一手  o(n) 求字符串的最长回文子串的manacher算法

//manacher算法
#include<bits/stdc++.h>
using namespace std;
char ss[5005],s[10005];
int p[5005];
int main()
{
    while(scanf("%s",ss)!=EOF)
    {
        int len=strlen(ss);
        s[0]='$';
        s[1]='#';
        int cnt=2;
        for(int i=0;i<len;i++)
        {
            s[cnt++]=ss[i];
            s[cnt++]='#';
        }
        s[cnt]=0;
        int id=0,ml=0;
        for(int i=1;i<cnt;i++)
        {
            if(i<p[id]+id) p[i]=min(p[2*id-i],p[id]+id-i);//如果i在已知的范围内
            else p[i]=1;
            while(s[i+p[i]]==s[i-p[i]]) p[i]++;//以i为中心扩充
            if(id+p[id]<i+p[i]) id=i;
            if(ml<p[i]) ml=p[i];
        }
        cout<<ml-1<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/CJLHY/p/7268292.html