1 条题解
-
2
本题题面很长,仔细读题后提取有用信息:
- ( 1)近似度:需要输出的这个数所对应的二进制与所给的n个整数所对应的二进制每一位上相同数字的数量。
- (2)给定一个整数k,用来规定标准十进制所对应的二进制的长度。不足m位用零补齐。
- (3)若有多种答案,需要输出二进制1最多的一种答案
- 解题思路:
-
- 很容易想到的是暴力,直接枚举每一个整数,转化成二进制,遍历n个数对应的二进制,求出相似度再取最大值,但是本题数据范围,二进制长度最大为31,遍历整数的范围为2^31,会TLE,不可行。
-
- 仔细观察样例,单独拆开每一位,我们可以考虑所求答案的十进制对应的二进制要想相似度最大,那么每一位都要尽可能与n个整数所对应的十进制的二进制每一位一样。从全局最优推到了局部最优,也就转化成了贪心思想。
- 贪心策略的证明在次不在赘述......
- 所以每一位的构造方法为max(n个整数这一位的0的数量累加,n个整数这一位的1的数量累加),如果0多这一位就是0,如果1多这一位就是1,如果0与1相等这一位也是1(需要满足(3))。
- tips:
- 答案会爆int,需要开long long
- 在求十进制数用pow也会爆int,需要强制类型转 化成long long。
- 时间复杂度O(Tn31),最坏在O(31*10^4),可以通过本题。 AC代码如下:
// Problem: 杨京昊的相亲计划 // URL: https://acm.nyist.edu.cn/p/900 // Memory Limit: 1 MB // Time Limit: 2000 ms // Date: 2023-10-21 14:01:32 // Author: XuJin // Motto:Thanks to time never giving up, give me a path of thorns // 看到你时总是感觉清风徐徐 // 本以为和你相识不会是偶遇 // 奈何你犹如过客、化作秋雨 // 只是经过我生命的一瓢柳絮 // 从不会真正有童话似的结局 // 我静静地写尽这些躁言丑句 // 本以为可以稍稍地缓解抑郁 // 却是徒增一场悲伤的脑补剧 // 你问我为什么说这么多? // 因为这题是杨京昊的相亲计划 // // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> #define xx first #define yy second #define I __int128 const int INF = 0x3f3f3f3f; const int N = 1e6 + 10; #define debug(x) cout << #x << "=" << x << '\n'; #define IOS \ ios::sync_with_stdio(false); \ cin.tie(0); \ cout.tie(0); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; int xx[] = {0, 0, 1, -1}; int yy[] = {1, -1, 0, 0}; int gcd(int a, int b) { return b ? gcd(b, a % b) : a; //求最大公约数 } ll yinshu(ll x) { //快速求一个数的因数个数 ll ans = 0; for (ll i = 2; i <= sqrt(x); i++) { if (x % i == 0) ans += 2; if (i * i == x) ans--; } return ans; } int a[N]; int cnt[N]; int t = 0; int ans1[N]; int ans2[N]; string cn[11000]; void erjin(int x) { t = 0; while (x) { cnt[++t] = x % 2; x /= 2; } } void solve() { /*给你 n个十进制数字 xi,你需要转化成长度为 ℓ的二进制数字(长度不够前边补 0 二进制数长度不会长于 ℓ,并且找到一个数字 y ,使得所有 xi与y的相似度和最大。 */ //----------------初始化------------------- memset(ans1, 0, sizeof(ans1)); memset(ans2, 0, sizeof(ans2)); int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; } string x = ""; //-----------存取每个十进制对应的二进制------------ for (int i = 1; i <= n; i++) { erjin(a[i]); for (int s = 1; s <= m - t; s++) { x += '0'; } for (int j = t; j >= 1; j--) { x += cnt[j] + '0'; } cn[i] = x; x = ""; } //--------------------贪心策略--------------------------- for (int i = 1; i <= n; i++) { string x1 = cn[i]; for (int j = 0; j < x1.size(); j++) { if (x1[j] == '0') { ans1[j]++; } else { ans2[j]++; } } } //---------------------构造字符串--------------------------- x = ""; for (int i = 0; i < m; i++) { if (ans1[i] <= ans2[i]) { x += '1'; } else { x += '0'; } } //------------------检查构造是否正确---------------- // cout<<x<<endl; //-----------------转化成十进制输出------------------------------ ll ans = 0; for (int i = x.size() - 1, k = 0; i >= 0; i--, k++) { ans += (ll)pow(2, k) * (x[i] - '0'); } cout << ans << endl; } int main() { IOS; int t; cin >> t; while (t--) { solve(); } }
- 1
信息
- ID
- 900
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 54
- 已通过
- 21
- 上传者