[Contests]BestCoder Round #87 (1001-1003)

来源:互联网 发布:二进制指数退避算法 编辑:程序博客网 时间:2024/05/22 00:13

1001 GCD is Funny

思路:

此题真迷;

先两两gcd得出的结果re, f[re]=1;

然后re与除了得出re的父母的其他数gcd

代码:

#include <bits/stdc++.h>using namespace std;//不互质返回trueconst int N=500+5;const int M=1000+5;int a[N];int f[M];int gcd(int x, int y){    return y?gcd(y,x%y):x;}int main(){    int t, n;    scanf("%d", &t);    while(t-->0){        memset(f,0,sizeof(f));        scanf("%d", &n);        for(int i=0; i<n; i++)            scanf("%d", &a[i]);        sort(a,a+n);        for(int i=0; i<n-1; i++)        for(int j=i+1; j<n; j++){            f[gcd(a[i],a[j])]=1;        }        int flag=1, len=n-1;        while(flag && len>=3){            len--;            flag = 0;            for(int i=1; i<=1000; i++)            if(f[i]){                for(int j=0; j<n; j++){                    int t = gcd(i,a[j]);                    if(!f[t]){                        f[t] = 1;                        flag=1;                    }                }            }        }        flag=0;        for(int i=1; i<=a[n-1]; i++)        if(f[i]){            if(flag)                printf(" ");            flag=1;            printf("%d", i);        }        printf("\n");    }    return 0;}


1002 Square Distance

思路:

比赛做了很久,怎么就没想出用dp做的呢,只怪自己太vegetable……

整个代码分为两步,让我们先用dp()判断是否可能,不可能就输出"Impossible" (without the quotes),否则按字典序最小的原则改动原数组

f[i][j] 代表从 i 到 (n/2-1) 的 j 代价能否实现,实现赋值1,for: n/2-1 to 0;

代码:

#include <bits/stdc++.h>using namespace std;const int N = 1000+5;char arr[N];int f[N/2][N];//从坐标i往后j代价能否实现,实现为1int n, m;int dp(){    memset(f,0,sizeof(f));    //注意边界条件    f[n/2][0] = 1;    for(int i=n/2-1; i>=0; i--){        if(arr[i]==arr[i+n/2]){            for(int j=0; j<=m; j++)                f[i][j] = f[i+1][j];//不改            for(int j=0; j<=m-2; j++)            if(f[i+1][j])                f[i][j+2] = 1;//改两个            continue;        }        for(int j=0; j<=m-1; j++)        if(f[i+1][j])            f[i][j+1] = 1;//改一个        for(int j=0; j<=m-2; j++)        if(f[i+1][j])            f[i][j+2] = 1;//改两个    }    if(f[0][m]) return 0;    return 1;}void change(){    int len=m, tmp;    for(int i=0; i<n/2; i++)    for(int j=0; j<26; j++){        tmp = 0;        if(arr[i] != j+'a') tmp++;        if(arr[i+n/2] != j+'a') tmp++;        if(f[i+1][len-tmp]){            arr[i] = arr[i+n/2] = j+'a';            len -= tmp;            break;        }    }}int main(){    int t;    scanf("%d", &t);    while(t-->0){        scanf("%d%d", &n, &m);        getchar();        gets(arr);        //判断是否存在        if(dp()){            printf("Impossible\n");            continue;        }        //以字典序最小原则改动原数组        change();        puts(arr);    }    return 0;}



1003 LCIS

思路:

一开始被题目迷惑了,LCIS是最长公共子序列,于是我的小伙伴就一直在写LCIS的dp然后TLE然后尝试优化_(:зゝ∠)_

其实这道题是求LIS,两个字符串分别求LIS最长(连续)上升子序列就可以!对,只是需要注意是连续(x,x+1……y-1,y)的就好;

int f[N];//代表以a[i]为结尾的最长【连续】递增序列长度
状态转移方程 f[a[i]] = max{f[a[i]-1]+1, f[a[i]]};

求出来之后for循环找最大值即可

代码:

#include <bits/stdc++.h>using namespace std;/*以a[i]为结尾的最长【连续】递增序列f[a[i]] = max{f[a[i]-1]+1, f[a[i]]};*/#define my_max(x,y) (x>y?x:y)#define my_min(x,y) (x<y?x:y)const int N = 1e5+5;const int M = 1e6+5;int a[N];int b[N];int fa[M];int fb[M];int n, m;void read(){    //memset(fa,0,sizeof(fa));    //memset(fb,0,sizeof(fb));    scanf("%d%d", &n, &m);    for(int i=0; i<n; i++){        scanf("%d", &a[i]);        fa[a[i]] = my_max(fa[a[i]], fa[a[i]-1]+1);    }    for(int i=0; i<m; i++){        scanf("%d", &b[i]);        fb[b[i]] = my_max(fb[b[i]], fb[b[i]-1]+1);    }}int main(){    int t;    scanf("%d", &t);    while(t-->0){        read();        int maxn=0;        for(int i=0; i<n; i++)            maxn = my_max(maxn, my_min(fa[a[i]],fb[a[i]]));//有个小陷阱坑了我!!!        printf("%d\n", maxn);        //注意fa(fb)里面是a[i](b[i])!!!        for(int i=0; i<n; i++) fa[a[i]] = 0;        for(int i=0; i<m; i++) fb[b[i]] = 0;    }    return 0;}

注意:

此题用memset超时,因为他会把数组按长度全部赋值,太慢,如果想用memset,请在代码最最前面加上
#pragma comment(linker, "/STACK:1024000000,1024000000")

反思:

一开始想成f[i]是以 i 为结尾的最长连续递增序列长度,当然就TLE了,做了很多无用功;

附上错误代码,引以为鉴;

#include <bits/stdc++.h>using namespace std;/*以i为结尾的最长【连续】递增序列f[i] = max{f[i-1]+1, f[i]};*/const int N = 1e5;int a[N];int b[N];int fa[N];int fb[N];int n, m;void read(){    scanf("%d%d", &n, &m);    for(int i=0; i<n; i++)        scanf("%d", &a[i]);    for(int i=0; i<m; i++)        scanf("%d", &b[i]);}void dp(){    for(int i=0; i<n; i++){        fa[i] = 1;        for(int j=0; j<i; j++)        if(a[i]==a[j]+1 && fa[j]+1>fa[i])            fa[i] = fa[j]+1;    }    for(int i=0; i<m; i++){        fb[i] = 1;        for(int j=0; j<i; j++)        if(b[i]==b[j]+1 && fb[j]+1>fb[i])            fb[i] = fb[j]+1;    }}int main(){    int t;    scanf("%d", &t);    while(t-->0){        read();        dp();        int maxn=0;        for(int i=0; i<n; i++)        for(int j=0; j<m; j++){            if(fb[j]==fa[i] && b[j]==a[i])                maxn = maxn>fb[j]?maxn:fb[j];        }        printf("%d\n", maxn);    }    return 0;}



0 0
原创粉丝点击