11.46.2020质检

B.是一个DP

有一群人非常喜欢ACM 比赛,只要是跟ACM 相关的东西他们都非常在意。有一天,他们在鲁东大学的校园里看到了一个仅由”A”、”C”、”M”这三个字符组成的横幅。一时兴起,他们想要知道这个横幅里出现了几次”ACM”,你也是其中的一员,请编写一个程序解决这个问题。

Input

输入只有一行,包含一个字符串ss(length(s)1e5 ),只含有A、C、M 这三种字母。

Output

在一行中输出给定的字符串中含有多少个ACM。最终的结果可能比较大,请对结果用1000000007 取余。

Samples

Input Copy
CAACAM
Output
2

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
const int mod=1000000007;
int main(){
    ll a=0,c=0,m=0;
    string str;
    cin>>str;
    for(int i=0;i<str.size();i++){
        if(str[i]=='A'){
            a++;
        }
        else if(str[i]=='C'){
            c+=a;
        }
        else if(str[i]=='M'){
            m+=c;
        }
        a=a%mod;
        c=c%mod;
        m=m%mod; 
    } 
    cout<<m%mod<<endl;
}
View Code

最近,一直在IT行业"搬砖"的程序员小张考虑到自己日渐稀疏的发量,决定跳槽去做工地"搬砖"做一名真正的民工,可是小张进入工地的第二天,包工头就交代给了小张另一个对发量极为不利的烧脑任务。现在有MM(1M20)块工地的石材,高度分别HiHi米(1Hi1000,000),这些石材的垒起来的总高度为SS,包工头让小张从这些石材中选出一些石材,垒出一个工作台,要求工作台的高度不能低于N 米(1N)1≤N),并且高出N米的长度越少越好,这样方便工人站在该工作台上作业。现在,你能帮小张从这M块石材中找出一个集合,垒起来的高度满足包工头的要求吗?如果不能满足条件,就输出能组成的最大高度。

Input

第一行MM 和NN 分别表示石材的个数和包工头要求的最低高度

第二到M+1M+1 行,H1,H2,,HMH1,H2,…,HM 表示每块石材的高度

Output

输出一个整数,表示满足包工头要求的石材垒出的高度。

Samples

Input Copy
5 16
3
1
3
5
6
Output
17

Source

2020年烟大校赛

一看数据范围1<=M<=20,第一反应就是二进制枚举
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
const int mod=1000000007;
int a[maxn];
int main(){
    int n,m;
    cin>>n>>m;
    ll p=0;
    for(int i=0;i<n;i++){
        cin>>a[i];
        p+=a[i]; 
    }
    if(p<=n){
        cout<<p<<endl;
        return 0;
    }
    int z=0x3f3f3f;
    int pp=0x3f3f3f;
    for(int i=0;i<(1<<n);i++){    
        ll sum=0;
        for(int j=0;j<n;j++){
            if(i&(1<<j)){
                sum+=a[j];
            }    
        }
        if(sum>=m){
            if((sum-m)<=pp){
                pp=sum-m;
                z=sum;
            }
        } 
    }
    cout<<z<<endl;
}

最近,一直在IT 行业"搬砖"的程序员小张考虑到自己日渐稀疏的发量,决定跳槽去做工地"搬砖"做一名真正的民工,可是小张进入工地的第一天,包工头就交代给了小张一个对发量极为不利的烧脑任务。现在有MM(1M200001≤M≤20000)块工地的石材,高度分别HiHi米(1Hi10000),这些石材的垒起来的总高度为SS,包工头让小张从这些石材中选出一些石材,垒出一个工作台,要求工作台的高度不能低于NN 米(1NS1≤N≤S),且石材的数目尽可能少。现在,你能帮小张从这M 块石材中找出一个集合,垒起来的高度满足包工头的要求吗?

Input

输入包含两行:

第一行MM 和NN 分别表示石材的个数和包工头要求的最低高度

第二到M+1M+1 行,H1,H2,,HMH1,H2,…,HM 表示每块石材的高度

Output

输出一个整数,表示垒出不低于NN 米的最少石材数目。

Samples

Input Copy
6 40
6
18
11
13
19
11
Output
3

Source

贪心:排序就行

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
const int mod=1000000007;
ll a[maxn];
bool cmp(int a,int b){
    return a>b; 
}
int main(){
    ll m,n;
    cin>>m>>n;
    for(int i=1;i<=m;i++){
        cin>>a[i];
    }
    sort(a+1,a+m+1,cmp);
    int sum=0; 
    for(int i=1;i<=m;i++){
        sum+=a[i];
        if(sum>=n){
            cout<<i<<endl;
            return 0;
        }
    }
}

Description

圣诞节快要到了,圣诞老爷爷要打包n 份糖果分给小朋友们,假设圣诞老爷爷已经打包好了m 份糖果了。恰好轮到小明了,小明因为是里面最小的小朋友,所以小明可以要两份,并且可以提出要求,小明希望能分到这n 份糖果中最多糖果的一份和最少糖果的一份,并且里面的糖果恰好为a 和b 个,这可难到圣诞老爷爷了,打包好的不可以拆开,剩下的nm 份都可以现装糖果,问能否满足小明的要求。

Inpu

输入包含两行:

第一行输入n,m,a,b 其中a 和b 的大小关系不确定。

第二行表示已经打包好的m 份糖果各自数量1n,m,a,b1000mn

Output

输出YES 或者NO

Samples

Input Copy
3 2 1 2
1 2
Output
YES

Source

2020年烟大校赛

就是考虑的情况比较多(主要是枚举n-m)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
const int mod=1000000007;
int aa[maxn];
int main(){
    int n,m,a,b;
    cin>>n>>m>>a>>b;
    if(a>b){
        swap(a,b);
    }
    int flag=1;
    for(int i=1;i<=m;i++){
        cin>>aa[i];
        if(aa[i]!=aa[1]){
            flag=0;//有不相同的 
        }
    } 
    if(a==b){ 
        if(flag==1&&n>=2){
            printf("YES
");
        }
        else{
            printf("NO
");
        }
        return 0;
    }
    sort(aa+1,aa+m+1);
    int mi=aa[1];
    int ma=aa[m];
    if(n<=1){
        printf("NO
");
        return 0;
    }
    else{
        if(n-m>=2){//当有大于2个的时候 
            if(mi<a||ma>b){//只要超过a  b就行 
                printf("NO
"); 
            }
            else{
                printf("YES
");
            }
            return 0;
        }
        else if((n-m)==1){
            if(mi<a||ma>b){//超过a  b肯定是不行的 
                printf("NO
");
                return 0;
            }
            else if(mi==a||ma==b){//必须再超过a b的情况下,至少一个端点是a,b 
                printf("YES
");
                return 0;
            }
            else{
                printf("NO
");
                return 0;
            }
        }
        else if(n==m){//不能再加的话,那就是a==mi,b==ma 
            if(a==mi&&b==ma){
                printf("YES
"); 
            }            
            else{
                printf("NO
");
            }
            return 0;
        }
    }
}

你喜欢套娃,根本停不下来。为了终止你的套娃行为,算法之神定义了两个函数g(如下图所示)使得你的套娃行为最终停止下来。

 

为了惩罚你的套娃行为,算法之神交给了你一项任务:

你需要进行QQ 次查询。在每一次查询中,你将被给予三个数字l,rl,r 和kk。你需要在区间[l,r][l,r]上找到满足公式g(x)=kg(x)=k 的xx 的数量(lxrl≤x≤r)。

Input

第一行给出整数QQ( 1Q21e5)表示有Q 次查询。

接下来的QQ 行,每行包括三个整数l,rl,r 和kk(1lr1e6 ,1k9

Output

对于每一次查询,输出单独一行,表示本次查询的结果。

Samples

Input Copy
4
22 73 9
45 64 6
47 55 7
2 62 4
Output
1
4
0
8

Hint

对于第一次查询,在区间[22,73]上,只有33 这个数字满足g(33)=9

因为g(33)=g(33)=g(9)=9

本题输入量较大,建议使用scanf 函数

Source

2020年烟大校赛


输出的时候肯定要o(1)输出
所以要用前缀和的思想,处理出来
ss[i][k]是指的是前i个数字为k的个数
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
struct ios {
    inline char gc(){
        static const int IN_LEN=1<<18|1;
        static char buf[IN_LEN],*s,*t;
        return (s==t)&&(t=(s=buf)+fread(buf,1,IN_LEN,stdin)),s==t?-1:*s++;
    }
    template <typename _Tp> inline ios & operator >> (_Tp&x){
        static char ch,sgn; ch = gc(), sgn = 0;
        for(;!isdigit(ch);ch=gc()){if(ch==-1)return *this;sgn|=ch=='-';}
        for(x=0;isdigit(ch);ch=gc())x=x*10+(ch^'0');
        sgn&&(x=-x); return *this;
    }
}io;
const int maxn=1e6+1000;
const int mod=1000000007;
int a[maxn][11];
int ss[maxn][11];
int s[maxn];
int p[maxn];
void inint(){
    for(register int i=1;i<=9;i++){
        a[i][i]++;
        for(register int j=1;j<=9;j++){
            ss[i][j]=ss[i-1][j]+a[i][j];
        } 
        s[i]=i;
    }
    int p;
    int sum,z;
    for(register int i=10;i<=1e6;i++){
        p=i;
        sum=1;
        while(p){
            if(p%10!=0){
                sum*=(p%10);
            }
            p/=10;
        }
        z=s[sum];
        a[i][z]++;
        for(register int j=1;j<=9;j++){
            ss[i][j]=ss[i-1][j]+a[i][j];
        } 
        s[i]=z;
    }
}
int main(){
    inint();
    int t;
    int l,r,k;
    scanf("%d",&t);
    while(t--){
        io>>l>>r>>k; 
        printf("%d
",ss[r][k]-ss[l-1][k]);
    } 
    return 0;
} 


一位拥有操作天气超能力的少女说道:“呐,现在开始就要放晴了哦~”

于是倾盆大雨停止了,天空放晴了……

她发现一些路边的石柱接住了一些雨水,她很好奇,这些石柱接住了多少雨水呢?如下图所示,这是nn 个石柱的侧视图,请计算按此排列的石柱接住了多少雨水(黑色为石柱,蓝色为雨水)。

Input

第一行,一个非负整数nn(0n3×1e4 ),表示有nn 个石柱。

第二行,nn 个非负整数组成的序列,表示石柱的高度height[i]0height[i]1e50i<n)。

Output

输出只有一行,包含一个非负整数numnum 表示石柱可以接住的雨水量。

Samples

Input Copy
12
0 1 0 2 1 0 1 3 2 1 2 1
Output
6
模拟了一下过程,我也承认它有点丑

就是找一个最大值,这个最大值肯定是要有贡献的,两边枚举,
#include<iostream>
#include<algorithm>
#define INF 2e9+10000
using namespace std;
const int maxn=5e6+100;
int a[maxn];
int main(){
    int n;
    cin>>n;
    int ma=0; 
    for(int i=1;i<=n;i++){
        cin>>a[i];
        ma=max(ma,a[i]);
    }
    int p;
    for(int i=1;i<=n;i++){
        if(a[i]==ma){
            p=i;
            break;
        }
    }
    int l=1;
    int ans=0;
    for(int i=2;i<=p;i++){
        if(a[i]>=a[l]){//比如说1 2 
            l=i;//那么这个1就没什么贡献了 
        }
        else{
            ans+=(a[l]-a[i]);//加贡献 
        }
    }
    int r=n; 
    for(int i=n-1;i>=p;i--){
        if(a[i]>=a[r]){
            r=i;
        }
        else{
            ans+=(a[r]-a[i]);
        }
    }
    cout<<ans<<endl;
} 

L:

在杂志社工作的小鹏在休息日突然接到老板丢过来的文本编辑任务,要求将一串漏洞百出的文本A 编辑为小鹏认为合理的文本B,小鹏一次可以对一个字符进行插入、删除和替换操作,每种操作需要耗费的时间分别对应为xyz分钟,然而小鹏一心只想看TT 分钟后的英雄联盟S10 全球总决赛,亲眼见证最喜欢的大乌龟战队夺冠。问:小明是否可以准时观看比赛?若可以,请告诉小明完成工作后还有多久开始比赛,否则输出比赛已经开始了多久。

Input

A

B

X Y Z T

Output

Yes (or No) 和一个整数(如果时间准时看比赛,请输出Yes 0)

Samples

Input Copy
abc
adc
5 3 2 2
Output
Yes 0

Hint

0<|A|,|B|<6000

1<x,y,z<10000

解析:这是一个dp的题,就是这两个字符串可能在更新后不同了,所以就有了

dp[i][j]=0x3f3f3f;
dp[i][j]=min(dp[i][j],dp[i-1][j]+y);//删除 有可能不一样长(比如a长) 
dp[i][j]=min(dp[i][j],dp[i][j-1]+x);//插入 有可能(b长) 

想想就知道了,第一个是如果a长的话就要删除,看看是不是最长

第二种就是,如果b长a短的话就是要添加

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=6e3+100;
char a[maxn];
char b[maxn];
int dp[maxn][maxn];
int x,y,z,t;//插入、删除和替换
int main(){
    scanf("%s",a+1);
    scanf("%s",b+1);
    scanf("%d%d%d%d",&x,&y,&z,&t);
    int lenn=strlen(a+1);
    int lenm=strlen(b+1);
    for(int i=1;i<=lenm;i++){
        dp[0][i]=i*x; 
    }
    for(int i=1;i<=lenn;i++){
        dp[i][0]=i*y;
    } 
    for(int i=1;i<=lenn;i++){
        for(int j=1;j<=lenm;j++){
            dp[i][j]=0x3f3f3f;
            dp[i][j]=min(dp[i][j],dp[i-1][j]+y);//删除 有可能不一样长(比如a长) 
            dp[i][j]=min(dp[i][j],dp[i][j-1]+x);//插入 有可能(b长) 
            if(a[i]==b[j]){
                dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
            }
            else{
                dp[i][j]=min(dp[i][j],dp[i-1][j-1]+z);
            }
        }
    }
    int z=dp[lenn][lenm];
    if(z<=t){
        printf("Yes %d",t-z);
    }
    else{
        printf("No %d",z-t);
    }
}
原文地址:https://www.cnblogs.com/lipu123/p/13991792.html