2017大学生程序设计竞赛 女生赛(A、E、C、G、B)( 水模拟 + 水模拟 + 前缀处理gcd + 思维模拟 + dp)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ShadowGhostH/article/details/80175510

A

题目大意:给出题号、时间、judge。计算最后的罚时。模拟可以过,学妹的代码,Orz

#include <bits/stdc++.h>
using namespace std;
const int maxn=3000;
int wa[maxn];
set<int>ac;
int cnt;
int ans;
void init()
{
    for(int i=0; i<maxn; i++)
        wa[i]=0;
    ac.clear();
    cnt=0;
    ans=0;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        init();
        int n,m;
        cin>>n>>m;
        for(int i=0; i<m; i++)
        {
            int t;
            string s1,s2;
            cin>>t>>s1>>s2;
            if(s2=="AC")
            {
                if(ac.count(t)) continue;
                else
                {
                    int tmp=(s1[1]-'0')*60+(s1[3]-'0')*10+s1[4]-'0';
                   // cout<<'*'<<tmp<<endl;
                    cnt++;
                    ans+=wa[t]+tmp;
                    ac.insert(t);

                }


            }
            else
            {
                wa[t]+=20;
            }
        }
        cout<<cnt<<' '<<ans<<endl;
    }
}

E

题目大意:求1~n的k次方的和,学弟的代码,直接预处理所有然后O(1)输出,Orz

#include <bits/stdc++.h>
using namespace std;

const long long md = 1e9 + 7;

long long ans[7][10010];
long long sm[7][10010];

void init(){
    for(long long i = 0; i <= 5; i++){
        for(long long j = 1; j <= 10000; j++){
            if(i == 0){
                ans[i][j] = 1;
            }else{
                ans[i][j] = ans[i - 1][j] * j % md;
            }
        }
    }
    for(long long i = 0; i <= 5; i++){
        for(long long j = 1; j <= 10000; j++){
            if(j == 1){
                sm[i][j] = ans[i][j];
            }else{
                sm[i][j] = (sm[i][j - 1] + ans[i][j]) % md;
            }
        }
    }
}

int main()
{
    int t;
    scanf("%d", &t);
    init();
    while(t--){
        int n, k;
        scanf("%d %d", &n, &k);
        printf("%lld\n", sm[k][n]);
    }
    return 0;
}

C

题目大意:给出一个序列,去掉任意一个数,问这个序列的最大gcd。可以处理前缀gcd和后缀gcd,然后枚举去掉哪个数。学妹的代码,Orz

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int qgcd[maxn];
int hgcd[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        qgcd[1]=a[1];
        for(int i=2;i<=n;i++)
        {
            qgcd[i]=(__gcd(qgcd[i-1],a[i]));
        }
        hgcd[n]=a[n];
        for(int i=n-1;i>=1;i--)
        {
            hgcd[i]=(__gcd(hgcd[i+1],a[i]));
        }
        int ans=-1;
        for(int i=1;i<=n;i++)
        {
            if(i==1)
            {
                ans=max(ans,hgcd[2]);
            }
            else if(i==n)
            {
                ans=max(ans,qgcd[n-1]);
            }
            else
            {
                ans=max(ans,__gcd(qgcd[i-1],hgcd[i+1]));
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

G

题目大意:给n个节点和n-1个操作,对应2~n的节点的操作,1表示和前面所有点连一条边,2表示无操作。问能否选取图中的一个子图,使得所有点只被一条边覆盖。

思路:对于所有操作为2的节点,他只能和编号比他大的,操作为1的节点连一条边。那么我们就从后往前遍历,看是否存在一个连续区间,2的个数比1多,若有,则不可。然后判断一下如果点数为奇数的话,也是不可以的。

这次是自己的代码。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;

int a[maxn];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        bool can = true;
        scanf("%d",&n);
        for(int i=0; i<n-1; i++)
            scanf("%d", &a[i]);

        int cnt = 0;
        for(int i=n-2; i>=0; i--)
        {
            if(a[i] == 1) cnt++;
            else if(a[i] == 2) cnt--;
            if(cnt<0) {
                can = false;
                break;
            }
        }

        if(n&1) can = false;

        if(can) puts("Yes");
        else puts("No");
    }

    return 0;
}

B

题目大意:有n个点,初始都是未标记的,每个点有自己的位置和把它标记的花费,转化之后,对于所有未标记的点,他们的花费是它距离左侧最近标记点的距离。问怎么标记使得整张图的花费最少。

思路:策略的话用dp考虑,先将所有点按照位置编号升序排序,然后考虑每个点标记与不标记情况下的花费。dp[0][i]为在i点不标记情况下前i个点的最小花费,dp[1][i]为在i点标记的情况下的最小花费。需要用前缀和预处理一下任意两点间全部为未标记点时的花费。

我自己的代码 -.-

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int maxn = 3e3+5;

struct Node{
    int id;
    int val;
    bool operator < (const Node &b) const{
        return id < b.id;
    }
}a[maxn];

LL dp[2][maxn];
LL dist[maxn][maxn];


int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        memset(dist, 0, sizeof dist);

        for(int i=0; i<n; i++)
            scanf("%d%d", &a[i].id, &a[i].val);

        sort(a, a+n);


        for(int i=0; i<n; i++){
            int temp = 0;
            for(int j=i+1; j<n; j++){
                temp += a[j].id - a[j-1].id;
                dist[i][j] = dist[i][j-1] + temp;
                //printf("#%d %d %d\n", i, j, dist[i][j]);
            }
        }


        dp[0][0] = a[0].val;
        dp[1][0] = a[0].val;

        for(int i=1; i<n; i++)
        {
            dp[0][i] = dp[1][0] + dist[0][i];    //[0][i]不在i建
            dp[1][i] = dp[1][0] + dist[0][i-1] + a[i].val;   //[0][i]为在i建

            //printf("*****%lld %lld\n", dp[0][i], dp[1][i]);

            for(int j=1; j<i; j++)
            {
                dp[0][i] = min(dp[0][i], dp[1][j]+dist[j][i]);                 //不在i建
                //dp[1][i] = min(dp[1][i], min(dp[0][j], dp[1][j]) + a[i].val);  //在i建
            }
            dp[1][i] = min(dp[0][i-1], dp[1][i-1]) + a[i].val;

            //printf("%d: %lld %lld\n", i, dp[0][i], dp[1][i]);
        }

        printf("%lld\n", min(dp[0][n-1], dp[1][n-1]));
    }
}

D

H

D和H留坑待补。。

猜你喜欢

转载自blog.csdn.net/ShadowGhostH/article/details/80175510