1 条题解

  • 0
    @ 2026-10-31 17:58:19

    思路

    问题转化: 当区块 ℓ\ell 的订单丢失时,要用剩下 n−1n-1 个区块的晶体:

    • 为其他 n−1n-1 个区块各制作 kk 块完整门牌;
    • 另外至少为区块 ℓ\ell 制作 11 块门牌。

    字符统计:

    • cnt[i][j]cnt[i][j]:第 ii 个区块的一块门牌中字符 jj 的个数;
    • tot[j]tot[j]:所有区块的一块门牌中字符 jj 的总个数。

    约束条件: 设区块 ℓ\ell 丢失,记

    o=tot[j]−cnt[ℓ][j]o=tot[j]-cnt[\ell][j]

    即其他区块一块门牌提供的字符 jj 的个数。剩余晶体中字符 jj 的总量是 o⋅mo\cdot m。给其他区块各做 kk 块需要 k⋅ok\cdot o 个,再为区块 ℓ\ell 做 11 块需要 cnt[ℓ][j]cnt[\ell][j] 个,于是

    k⋅o+cnt[ℓ][j]≤o⋅m.k\cdot o+cnt[\ell][j]\le o\cdot m.

    求 kk 的最大值: 对每个满足 cnt[ℓ][j]>0cnt[\ell][j]>0 的字符 jj:

    • 若 o=0o=0:没有其他区块提供字符 jj,连区块 ℓ\ell 的 11 块都做不出来,无解;
    • 若 o⋅m<cnt[ℓ][j]o\cdot m<cnt[\ell][j]:同理,连 1 块都做不出来,无解;
    • 否则 $k\le\left\lfloor\dfrac{o\cdot m-cnt[\ell][j]}{o}\right\rfloor$。

    对区块 ℓ\ell 中出现的所有字符取 kk 的最小值即为该区块的答案;只要有一个字符无解,该区块就输出 −1-1。实现时对每个 ℓ\ell 扫一遍 26 个字母即可。

    复杂度: 时间 O(∑∣si∣+26n)O(\sum|s_i|+26n),空间 O(26n)O(26n)。

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define dd double
    #define str string
    #define el cout << '\n'
    #define re return
    #define ff first
    #define ss second
    #define pll pair<int,int>
    #define pdd pair<dd,dd>
    #define all(x) x.begin(),x.end()
    #define pb push_back
    using namespace std;
    
    void go(){
        int n,m;cin>>n>>m;               // 区块数、每个区块可用的晶体份数
        vector<vector<int>>cnt(n, vector<int>(26, 0));   // 每个区块一块门牌的字符计数
        vector<int>tot(26, 0);                          // 所有区块一块门牌的字符总计数
    
        for(int i=0;i<n;i++){
            str s;cin>>s;
            for(char c:s){
                cnt[i][c-'A']++;
                tot[c-'A']++;
            }
        }
    
        // 逐个假设区块 i 的订单丢失
        for(int i=0;i<n;i++){
            int mi = 1e9;                // 该区块能制作的最大 k
            for(int j=0;j<26;j++){
                if(cnt[i][j]==0)continue;        // 该块门牌里没有这个字符,无需约束
    
                int lst = (tot[j] - cnt[i][j]);  // 其他区块一块门牌提供的该字符数
                // 其他区块完全不提供,或剩余晶体连 1 块都不够
                if(lst==0 or (lst*m<cnt[i][j])){mi = -1;break;}
    
                // 由 k*lst + cnt[i][j] <= lst*m 解出 k 的上界
                mi =  min(mi, (lst*m-cnt[i][j])/(tot[j] - cnt[i][j]));
            }
    
            cout<<mi<<' ';               // -1 表示无解
        }
        el;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);cout.tie(nullptr);
        int _=1;                         // 本题只有单组数据
        while(_--){
            go();
        }
        return 0;
    }
    
    • 1

    信息

    ID
    25
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者