黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)

传送门(点击传送 )

A. 数组截取

题意:
  从数列中截取和为 k 的序列,越长越好。
思路:
  双指针搞一遍,当区间内和小于等于 k 时右指针向右移。之后当区间内和大于 k 时,左指针向右移。建议边处理边读。数据过大注意用快读。
代码:

#include<iostream>
using namespace std;
long long num[20000005];
long long read() {
    long long x = 0, w = 1;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x;
}
inline void write(long long x) {
    static int sta[35];
    int top = 0;
    do {
        sta[top++] = x % 10, x /= 10;
    } while (x);
    while (top) putchar(sta[--top] + 48);
}
int main()
{
    long long n,k,sum=0,ans=-1,i=1,j=1;
    n=read();k=read();
    while(i<=n){
        while(sum<=k && i<=n){
            num[i]=read();
            sum+=num[i];
            if(sum==k){
                ans=(i-j+1)>ans?(i-j+1):ans;
            }
            i++;
        }
        while(sum>k && i>=j){
            sum-=num[j];
            j++;
        }
        if(sum==k){
            ans=(i-j)>ans?(i-j):ans;
        }
    }
    if(ans==-1) puts("-1");
    else write(ans);
    return 0;
}

B. 群友们在排列数字

题意:
  群友们在玩一个游戏,共 n 个人在玩 每个人要在 0-(n-1) 中选一个数,注意每个数只能选择一次。依次选择后拼成的数字能被 k 整除的个数。
思路:
  暴力枚举每一个人选择的数字即可,可用递归。
代码:

#include<bits/stdc++.h>
using namespace std;
bool flag[15];
int n,ans;
long long sum=0,k;
void solve(int now){
    if(now>n){
        if(sum%k==0) ans++;
        return;
    }
    for(int i=0;i<n;i++){
        if(!flag[i]){
            sum*=10;
            sum+=1ll*i;
            flag[i]=true;
            solve(now+1);
            flag[i]=false;
            sum/=10;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>k;
    solve(1);
    if(ans==0) cout<<-1<<endl;
    else cout<<ans<<endl;
    return 0;
}

C. gg查成绩

题意:
  已知 n 个同学,m 次询问,每次询问第 x 和第 y 同学之间所有同学的成绩和(包括 x 和 y )。
思路:
  预处理求出前缀和数组,作差即可。
代码:

#include<bits/stdc++.h>
using namespace std;
long long sum[1000005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    long long n,m,get_num;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>get_num;
        sum[i]=sum[i-1]+get_num;
    }
    int a,b;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        cout<<sum[b]-sum[a-1]<<endl;
    }
    return 0;
}

D. issue与lifehappy给学生分组

题意:
n 个学生,划分成 m 组,让和的最大值最小。
思路:
  进行二分处理,对于每一次的值,判断该值是否符合条件。(注意题目中的是选取连续队列),预处理边界 l 为所有数的最大值,r 为所有数之和。
代码:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
long long num[1000005];
int n,m;
bool judge(ull x){
    int cont=1;
    ull sum=0;
    for(int i=1;i<=n;i++){
        sum+=num[i];
        if(sum>x){
            sum=num[i];
            cont++;
        }
        if(cont>m) return false;
    }
    return true;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    ull l=0,r=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>num[i];
        r+=num[i];
        l=l>num[i]?l:num[i];
    }
    while(l<r){
        ull mid=(l+r)>>1;
        if(judge(mid)){
            r=mid;
        }else{
            l=mid+1;
        }
    }
    cout<<l<<endl;
    return 0;
}

E. 删删删越小越好

题意:
  给出一个数,求出删去 k 个字符后的最小值。
思路:
当然是让越靠近左边的数字越小越好(即高位小),所以从左到右依次处理字符,对于第 i 个位置的数字,如果左边的数字(1 ~ i-1)位置有比它大的,则删去第 i 个数字左边的数字,直到无法删除或者第 i 个数字左边的数字都小于等于第 i 个数字。剩下的即为答案。(不知道不用快读行不行)
代码:

#include<bits/stdc++.h>
using namespace std;
inline string read()
{
    char ch = getchar();
    string st1 = "";
    while ((ch >= '0') && (ch <= '9'))
        st1 += ch, ch = getchar();
    return st1;
}
int read_n() {
    int x = 0;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x;
}
int main()
{
    bool flag=false;
    string str=read();
    int k=read_n(),cont=0;
    deque<char>que;
    for(int i=0;i<str.size();i++){
        if(cont==k) que.push_back(str[i]);
        else if(que.empty()) que.push_back(str[i]);
        else{
            while((!que.empty())&& cont<k && str[i]<que.back()){
                que.pop_back();
                cont++;
            }
            que.push_back(str[i]);
        }
    }
    while(cont<k){
        que.pop_back();
        cont++;
    }
    while(!que.empty()){
        if(flag){
            putchar(que.front());
        }else{
            if(que.front()!='0'){
                putchar(que.front());
                flag=true;
            }
        }
        que.pop_front();
    }
    if(!flag) putchar('0');
    return 0;
}

F. happy的异或运算

题意:
  给出一个整数 n,请求出 1-n 之间选取两个数进行异或最大能得出多大。
思路:
  让 n 对应二进制每一位都为 1 即为答案。
代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n,ans=0;
    cin>>n;
    while(n){
        ans<<=1;
        ans|=1;
        n>>=1;
    }
    cout<<ans<<endl;
    return 0;
}

G. Alan%%%

题意:
  如果一行中除去空格后包括Alan则这一行所有的%为有效%,问一共有多少个有效%。
思路:
  每次读一行,暴力对比ALan即可(遇到空格则忽略直接下一个字符)。
代码:

#include<bits/stdc++.h>
using namespace std;
string model="Alan";
int main(void)
{
    int n,ans=0,cont,p;
    string str;
    bool flag;
    cin>>n;
    getchar();
    for(int tc=1;tc<=n;tc++){
        p=0;
        cont=0;
        flag=false;
        getline(cin,str);
        for(int i=0;i<str.size();i++){
            if(str[i]==' ') continue;
            if(str[i]=='%') cont++;
            if(!flag){
                if(str[i]==model[p]){
                    p++;
                    if(p==4) flag=true;
                }else{
                    if(str[i]==model[0]) p=1;
                    else p=0;
                }
            }
        }
        if(flag) {
            ans+=cont;
        }
    }
    cout<<ans<<endl;
    return 0;
}

H. cg写项目 & I. cg写项目加强版

题意:
  很多用户数据,以用户的用户名为基准进行一下排序,短的在前,同样长度按照字典序小的在前,同用户名先输入的在前面。
思路:
  直接 sort 一下加一下排序条件即可。
代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
    int loc;
    string s,m,x,h;
}que[1000005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>que[i].s>>que[i].m>>que[i].x>>que[i].h;
        que[i].loc=i;
    }
    sort(que+1,que+1+n,[](const node &a,const node &b){
        if(a.s.size()==b.s.size()){
            if(a.s==b.s){
                return a.loc<b.loc;
            }else{
                return a.s<b.s;
            }
        }else{
            return a.s.size()<b.s.size();
        }
    });
    for(int i=1;i<=n;i++){
        cout<<que[i].s<<" "<<que[i].m<<" "<<que[i].x<<" "<<que[i].h<<endl;
    }
    return 0;
}

J. 比赛开始了清楚姐姐喊了一句:签到了签到了

题意:
  输出最先做出题目的人的序号。
思路:
  签到题怎么写都行。
代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
    int loc,num;
}que[10005];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>que[i].num;
        que[i].loc=i;
    }
    sort(que+1,que+1+n,[](const node &a,const node &b){
        if(a.num==b.num) return a.loc<b.loc;
        else return a.num<b.num;
    });
    cout<<que[1].loc<<endl;
    return 0;
}