2018.5.30 T3 通往天国的倒计时(countdown.cpp/c/pas)

题目背景Background

由于模拟赛的良心,相信大家都已经过了t2,于是放这道t3 给大家放松一下

题目描述Description

qiancl 得到了一个长度为n 的序列ai ,他用这个序列构出了一个大小为n*n 的矩阵 g i j ,构造方
法为: g i j = g c d ( a i , a j ) ,比如 a i = 4 , 3 , 6 , 2

g i j = [ 4 1 2 2 1 3 3 1 2 3 6 2 2 1 2 2 ]

测试数据对应数据范围

其中12个测试点 1<=k,a,b<=105
其中6个测试点 233<=k<=250,且1<=a,b<=108
剩下32个测试点 1<=k,a,b<=1018
然而qiancl 丢失了原本的序列i a ,而且矩阵里的每个数都被打乱了,请你还原原来的序列i a

输入描述(countdown.in) Input Description

第一行一个整数n,接下来一行n*n 个数表示矩阵里的每个数,随机排列

输出描述(countdown.out) Output Description

一行n 个整数从小到大排列表示还原出的序列

样例输入Sample Input

4
2 1 2 3 4 3 2 6 1 1 2 2 1 2 3 2

样例输出Sample Output

2 3 4 6

数据范围及提示Data Size & Hint

对于20%的数据,n<=3
对于另20%的数据,n<=6, ij g <=10
对于100%的数据,n<=400,1<= ij g <=100w


发动大眼观察法,发现ans一定在给出序列中,再观察,最大的6一定在ans中,4也在ans中
由此猜想:ans在最大的几个数中,对于已经找出的ans,我们需要减去它们的gcd,发现正好
然后就没了

#include <map>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=405;
int n,cnt;
int a[N*N],ans[N],vis[N*N];
map<int,int>mp;
int gcd(int x,int y) {return !y?x:gcd(y,x%y);}
int main() {
    freopen("countdown.in","r",stdin);
    freopen("countdown.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n*n;i++) 
        scanf("%d",&a[i]);
    sort(a+1,a+n*n+1);
    for (int i=1;i<=n*n;i++)
        if (a[i]!=a[i-1]) mp[a[i]]=i;
    for (int i=n*n;i>=1;i--) {
        if (vis[i]) continue;
        ans[++cnt]=a[i];
        for (int j=1;j<cnt;j++) {
            int gd=gcd(ans[j],ans[cnt]);
            int v=mp[gd];
            vis[v]=1;vis[v+1]=1;mp[gd]=v+2;
        }
    }
    for (int i=n;i>=1;i--)
        printf("%d ",ans[i]);
}

帮同学写了桶排版,简单些

#include <cstdio>
#include <algorithm>
using namespace std;
int gcd(int x,int y) {return !y?x:gcd(y,x%y);}
int n,mx,cnt;
int a[1000007],ans[407];
int main() {
    freopen("countdown.in","r",stdin);
    freopen("countdown.out","w",stdout);
    scanf("%d",&n);
    for (int i=1,w;i<=n*n;i++) {
        scanf("%d",&w);
        a[w]++;
        mx=max(w,mx);
    }
    for (int i=mx;i>=1;i--) {
        while(a[i]) {
        ans[++cnt]=i;
        a[i]--;
        for (int j=1;j<cnt;j++)
            a[gcd(ans[j],i)]-=2;
        }
    }
    for (int i=cnt;i>=1;i--)
        printf("%d ",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80514670
T3