1 条题解
-
0
思路
问题转化: 当区块 的订单丢失时,要用剩下 个区块的晶体:
- 为其他 个区块各制作 块完整门牌;
- 另外至少为区块 制作 块门牌。
字符统计:
- :第 个区块的一块门牌中字符 的个数;
- :所有区块的一块门牌中字符 的总个数。
约束条件: 设区块 丢失,记
即其他区块一块门牌提供的字符 的个数。剩余晶体中字符 的总量是 。给其他区块各做 块需要 个,再为区块 做 块需要 个,于是
求 的最大值: 对每个满足 的字符 :
- 若 :没有其他区块提供字符 ,连区块 的 块都做不出来,无解;
- 若 :同理,连 1 块都做不出来,无解;
- 否则 $k\le\left\lfloor\dfrac{o\cdot m-cnt[\ell][j]}{o}\right\rfloor$。
对区块 中出现的所有字符取 的最小值即为该区块的答案;只要有一个字符无解,该区块就输出 。实现时对每个 扫一遍 26 个字母即可。
复杂度: 时间 ,空间 。
代码
#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
- 上传者