
Mathematics
发布日期:2021-05-07 06:55:13
浏览次数:29
分类:精选文章
本文共 1355 字,大约阅读时间需要 4 分钟。
M a t h e m a t i c s Mathematics Mathematics
题目链接:
题目
有 n n n堆石子,从 1 ∼ n 1\sim n 1∼n编号,其石子总数为 2 k 2^k 2k。
每次可以选择两堆石子 a a a和 b b b,满足 a a a堆的石子数不比 b b b堆的多,记 c c c为 a a a的石子数。然后可以进行以下操作:从 b b b堆石子中拿 c c c这么多的石子到 a a a堆中。
要求你给出一个方案,使得最后有一堆石子的数目达到 2 k 2^k 2k。
输入
第一行两个正整数 n n n, k k k。
第二行 n n n个非负数 a i a_i ai。输出
输出若干行,每行两个数 a a a , b b b,表示每次操作中的两堆石子的编号,必须满足题中所给的大小关系!
样例输入
2 23 1
样例输出
2 23 1
数据范围
对于 30 % 30\% 30%的数据, n = 2 n\!=\!2 n=2;
对于 100 % 100\% 100%的数据, n < = 100000 n\!<\!=\!100000 n<=100000, k < = 31 k\!<\!=\!31 k<=31。思路
这道题就是暴力,很暴力。
因为每一次操作就会是石子多的给石子少的,让石子少的加一倍。
而且它没有说要用最快的方法,那我们就可以慢慢来。 我们可以直接从小到大枚举位数,因为石子总和加起来一定是 2 k 2^k 2k,所以我们如果一位一位的处理,那么我们每一位枚举完之后,那一位所有的数一定都是 0 0 0,所以接下来往高位枚举无论怎么放石子,之前的位数都会是 0 0 0。 所以我们就可以用这种方法,得出答案。代码
#includeusing namespace std;int n, k, a[100001], t;int main() { scanf("%d %d", &n, &k);//读入 for (int i = 1; i <= n; i++) scanf("%d", &a[i]);//读入 for (int i = 1; i <= k; i++)//枚举位数 for (int j = 1; j <= n; j++)//枚举每一个数 if (a[j] & (1 << (i - 1))) { //这个数这一位是1 if (!t) t = j;//之前这一位都全部是0了 else { //之前的数还有是1的,可以操作 if (a[t] < a[j]) { //现在的大 printf("%d %d\n", t, j); a[j] -= a[t]; a[t] *= 2; t = 0; } else { //之前的大 printf("%d %d\n", j, t); a[t] -= a[j]; a[j] *= 2; t = 0; } } } return 0;}
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2025年03月22日 15时40分23秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
764. Largest Plus Sign
2021-05-09
214. Shortest Palindrome
2021-05-09
916. Word Subsets
2021-05-09
869. Reordered Power of 2
2021-05-09
1086 Tree Traversals Again
2021-05-09
1145 Hashing - Average Search Time
2021-05-09
1131 Subway Map
2021-05-09
1127 ZigZagging on a Tree
2021-05-09
1062 Talent and Virtue
2021-05-09
1060 Are They Equal
2021-05-09
1045 Favorite Color Stripe
2021-05-09