雪花挂饰 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;
}

 

posted @ 2019-11-11 20:26  寒方  阅读(232)  评论(0编辑  收藏  举报