D.开关

从后往前扫一遍。

2020 计蒜之道 热身赛_计蒜客

 

#include <bits/stdc++.h>
using namespace std;
string s;
int main(){
    int n;
    scanf("%d",&n);
    cin>>s;
    bool flag = 1;
    int ans = 0;
    for(int i=n-1;i>=0;i--){
        if(flag && s[i]=='1' || !flag && s[i]=='0'){
            flag=!flag;
            ans+=1;
        }
    }
    printf("%d\n",ans);
}

E. 构造字符串

二分

2020 计蒜之道 热身赛_编程_02

 

 

#include <bits/stdc++.h>
using namespace std;

int num[26];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<26;i++){
        scanf("%d",&num[i]);
    }
    long long l = 0, r = 1e15;
    while(l<r){
        long long mid = (l+r+1)/2;
        //printf("%d %d\n",l,mid);
        long long now = 0;
        for(int i=0;i<26;i++){
            now += num[i]/n;
        }
        if(now>=mid) l = mid;
        else r = mid-1;
    }
    printf("%lld\n",l);
}

G. 字符串

字符串HASH+前缀和+map

2020 计蒜之道 热身赛_计蒜客_03

 

 

#include <bits/stdc++.h>
using namespace std;

int cnt[30],sum[200001][30];
typedef unsigned long long ull;
const ull base = 233333;
ull Hash[200001],pw[200001];
string s, t;
map <ull, bool> mp;
int main(){
    cin >> s;
    cin >> t;
    for(int i=0;i<s.size();i++){
        cnt[s[i]-'a']++;
    }
    pw[0] = 1;
    for(int i=1;i<=t.size();i++){
        pw[i] = pw[i-1]*base;
        Hash[i] = Hash[i-1]*base + t[i-1];
        for(int j=0;j<26;j++){
            sum[i][j] = sum[i-1][j]; 
        }
        sum[i][t[i-1]-'a']+=1;
    }
    int ans = 0;
    for(int l=1;l<=t.size();l++){
        int r = l+s.size()-1;
        if(r>t.size()) break;
        bool flag = true;
        for(int i=0;i<26;i++){
            if(sum[r][i]-sum[l-1][i]!=cnt[i]) flag = false;
        }
        if(!flag) continue;
        ull hashvalue = Hash[r] - Hash[l-1]*pw[r-l+1];
        if(mp.count(hashvalue)) continue;
        mp[hashvalue] = 1;
        ans++;
    }
    printf("%d\n",ans);
    
    
}