2024.07.13科大讯飞提前批

1. 找01

牛牛拥有一个长度为 n 的01 串,现在他想知道,对于每个字符,在它前面的最近的不同字符的下标是多少?

两个下标记录上一个01位置
int main(int argc, char *argv[]) {

    int T;
    cin>>T;//测试组数
    while(T--){
        int n;
        cin>>n;
        string s;
        cin>>s;
        int idx0 =- 1; int idx1 = -1;//分贝记录上一个0和1的位置
        vector<int> res(n,-1);
        for(int i=0;i<n;i++){//遍历所有字符
            if(s[i]=='0'){
                res[i] = idx1;
                idx0 = i;
            }
            else{
                res[i] = idx0;
                idx1 = i;
            }
        }
        for(int i=0;i<n;i++){
            if(i>0) cout<<" ";
            if(res[i]==-1) cout<<res[i];
            else cout<<res[i]+1;
        }
        cout<<endl;
    }
    return 0;
}

2. 不能出现太多

给定n个数字A1,A2,..An,请求出这些数字中出现次数小于等于k的最小的数。

先哈希计数再筛选可以避免排序
int main(int argc, char *argv[]) {

    int n; int k;
    cin>>n;
    cin>>k;
    vector<int> nums(n);
    unordered_map<int,int> m;
    for(int i=0;i<n;i++){
        cin>>nums[i];
        m[nums[i]]++;
    }
    int res = INT_MAX;
    for(auto num:nums){
        if(m[num]>k) continue;
        res = min(res,num);
    }
    if(res==INT_MAX) cout<<-1;
    else cout<<res;
    
    return 0;
}

3. 乘2除2

给出一个大小为n的序列a,每次操作可以选择序列a中的一个数x,把x变成x*2或者[x/2](对同一个a可以操作多次但不能既进行乘操作又进行除操作)。
问最少操作多少次使得a是不下降的。

因为这里操作后是倍增,可以动态规划,同时记录每一位经过任意除和乘操作后得到的数以及对应次数,接着下一个数可以从该状态转移

const long long MAXN = 1e18;
unordered_map<long long,int> dp[20005];//暴力哈希列举所有操作次数

int main(int argc, char *argv[]) {

    int n; 
    cin>>n;
    vector<int> nums(n);
    for(int i=0;i<n;i++)
        cin>>nums[i];
    //考虑到最小操作次数的无后效性,可以使用动态规划,其实暴力列举所有操作次数的可能,然后转移到下一个状态记录列举即可
    dp[0][1] = 0;//不进行任何操作,初始操作数为0
    for(int i=0;i<n;i++){//遍历数字序列
        for(auto &[j,steps]:dp[i]){//从上一个状态开始转移,初始状态时最小值1,操作次数为0
            if(nums[i]>=j){//已经递增的话,可以选择不变,变小
                if(dp[i+1].find(nums[i])==dp[i+1].end()||dp[i+1][nums[i]]>steps)
                    dp[i+1][nums[i]] = steps;
                //变小
                long long num = nums[i];
                int cnt = 0;
                while(num/2>=j){
                    cnt++;
                    num/=2;
                    if(dp[i+1].find(num)==dp[i+1].end()||dp[i+1][num]>steps+cnt)
                        dp[i+1][num] = steps+cnt;
                }
            }
            else{//否则只能选择变大维持递增
                long long num = nums[i];
                int cnt = 0;
                while(num<j){
                    num*=2;
                    cnt++;
                }
                if(dp[i+1].find(num)==dp[i+1].end()||dp[i+1][num]>steps+cnt)
                    dp[i+1][num]=steps+cnt;
            }
        }
    }
    int res = INT_MAX;
    for(auto &[k,v]:dp[n])
        res = min(res,v);
    cout<<res;
    return 0;
}
posted @ 2024-09-03 13:26  失控D大白兔  阅读(11)  评论(0编辑  收藏  举报