补题

暑假友谊赛No.2——冰

题意:n个人,m句话,用一个字符串表示一个人是否会说第i句话。
选出一些人组成一个队列,要求按原来的顺序但可以不连续,
相邻的两个人不能会说同样的话。
求队列的种数。

思路:状态压缩dp,把字符串转换成01字符串。
0表示不说,1表示说。
相邻两人不能会说同样的话转换成2个01串相与必须为0

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,M=300,MOD=998244353;
string s;
int f[M][M];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    int ans=0;
    while(n--){
        int a=0;
        cin>>s;
        
        for(int i=0;i<s.size();i++)
            a=a<<1|(s[i]=='o');            //处理01串的每一位,或运算如果说这句话就为1,否则为0
        int high=a>>8,low=a&255,res=1;         //分成高8位和低8位用二维数组存
        for(int i=0;i<(1<<8);i++){
            if(!(high&i))                             //枚举所有状态,找到符合高8位相与为0的情况
                res=(res+f[i][low])%MOD;      //进一步判断低位是否也相与为0(低位已经被处理过,所以二维索引就是low)
            }
        }
        ans=(ans+res)%MOD;                //每个字符串处理完后答案累加
        for(int i=0;i<(1<<8);i++){
            if(!(low&i)) f[high][i]=(f[high][i]+res)%MOD;          //枚举所有状态,保留高位,低位满足条件相与为0
        }
        //cout<<res<<endl;
    }
    cout<<ans<<endl;
    return 0;
}

SMU Summer 2023 Contest Round 7——D Yet Another Monster Killing Problem

题意:n个怪物,都有自己的力量值a,
m个英雄,都有自己的力量值p和能连续打怪的数量s,
按顺序打怪,一天只能选择一个英雄,当英雄力量>怪物力量怪物被打败,否则 一天结束,下一天仍需继续打这个怪物。
英雄使用次数不限,问最少几天能打败所有怪物。

思路:两个约束条件,力量值和耐力值,
预处理数组h[],索引表示耐力,数组值表示相同耐力下的最大力量值,
倒着跑一遍h[],如果出现后面的力量大于前面的力量,把前面的力量更新为后 面的力量。(此时后面的耐力和力量都优与前面,选后者更优)
双指针,如果当前怪可以被打败,就往后延申。不能则天数++。

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N=2e5+10;
#define inf 0x3f3f3f3f

void solve() {
    int n, m;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i ++) cin >> a[i];
    cin >> m;
    vector<int> h(n + 1);
    for (int i = 1; i <= m; i ++) {
        int p, s;
        cin >> p >> s;
        h[s] = max(h[s], p);           //耐力相同,取更大的力量值
    }
    for (int i = n - 1; i >= 0; i --) 
    h[i] = max(h[i + 1], h[i]);            //如果后者力量耐力都优于前者则把前者力量更新为后者力量

    int ans = 0;
    for (int l = 1, r; l <= n; l = r) {
        r = l;
        int x = 0;
        while (r <= n && h[r - l + 1] >= max(x, a[r])) {     //英雄力量值大于区间里怪物力量的最大值
            x = max(a[r], x);
            r ++;
        }
        if (r == l) {             //遇到无法打败的怪,即英雄力量最大值<怪物力量最大值,失败
            cout << "-1\n";
            return ;
        }
        ans ++;                   //无法满足所有条件,天数+1
    }
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}


posted @ 2023-07-29 11:05  WW爆米花  阅读(4)  评论(0编辑  收藏  举报