雪花挂饰 v2 (电子科技大学第十届 ACM 趣味程序设计竞赛(第三场))(桶排序)
雪花挂饰 v2
题目描述
这里没有雪……
Yuzuru 想给 Kanade 做一个雪花挂饰。这次 Yuzuru 吸取了 HSD 桑的教训,没去找事多的 HeRaNO ,
他决定自己做。
Yuzuru 一共有 n 片雪花,为了做出最好看的雪花挂饰,他给每片雪花定了一个美丽值 ai 。他想先把这 片雪花排成一排,但是这样一排雪花中美丽值大的雪花过于集中会导致审美疲劳,因此 Yuzuru 定义了一个值m,如果相邻两片雪花的美丽值之和可以整除m,就称这一对雪花是美丽的。
现在 Yuzuru 想知道,将这n片雪花重新排列后,这个序列中最多有多少对美丽的雪花。
输入
从 snowflakes.in 读入以下数据:
第一行两个整数 n,m,表示雪花片数和定义的值m;
第二行n个整数,第i个整数为ai。
输出
输出到 snowflakes.out。
输出一行一个整数,表示重新排列后,这个序列中最多有多少对美丽的雪花。
样例
样例输入 1
3 2
1 2 3
样例输出 1
1
样例说明 1
可能的排列共6种,其中有4种美丽值为1,3的雪花相邻时答案取得最大值1 。
1 雪花挂饰 v2
1.1 题目描述
给定一个数列 faig,现将其重新排列,问重排后最多可能有多少 i 2 [1; n 1],满足 (Ai
Ai+1) 0 (mod m)。
数据范围:1 n;m 106; 1 ai 109。
1.2 题解
1.2.1 算法一
很显然,我们枚举这个数列的每一个排列,统计答案即可。
时间复杂度:O(n n!),空间复杂度:O(n)。
期望得分:30 分。
1.2.2 算法二
其实这部分并没有想清楚有什么算法能匹配上的,给正解打挂的同学留点分……
时间复杂度:O(n2),空间复杂度:O(n)。
期望得分:60 分。
1.2.3 算法三
注意到将式子展开,可以变为 Ai mod m + Ai+1 mod m 0 (mod m),于是我们记录数列中数
除 m 余 0; 1; 2; : : : ;m 1 的数的个数,记除 m 余 i 的数有 ci 个,这样重排后就要使得余数和为 m
或余数都为 0 的数尽可能相邻。
首先考虑第一种情况,即 i + j = m 时,如果 ci = cj,则最多能构造 2ci-1 对,否则,可以把
个数更多的元素放在外面,构造 2minfci; cjg 对。
再考虑第二种情况,即 i = j = 0 时,可构造 c0-1 对。
第一种情况遍历一遍数组即可,第二种情况可以直接算出来。需要注意不要重复统计,并且当
ci = cj = 0 时需要特判,否则会出现计算错误。
时间复杂度:O(n + m),空间复杂度:O(m)。
期望得分:100 分。
1.3 来源
电子科技大学第十届 ACM 趣味程序设计竞赛(第三场),有加强。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> using namespace std; const int maxn = 1e6 + 10 ; int n,a[maxn],m; int f[maxn],ans; int main() { cin>>n>>m; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); f[a[i]%m]++; } for(int i=1;i<=m/2;i++) if(i==m-i && f[i]) ans+=f[i]-1; else if(f[i]==f[m-i] && f[i]) ans+=2*f[i]-1; else ans+=2*min(f[i],f[m-i]); if(f[0]) ans+=f[0]-1; cout<<ans<<endl; return 0; }