2017中国大学生程序设计竞赛 - 女装专场

Automatic Judge

算罚时。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>

using namespace std;

bool v[2000];
int ts[2000];

int main(){
    int T,n,m,mins,secs,num;
    string st;
    cin>>T;
    while(T--){
        cin>>n>>m;
        int ans = 0, tot = 0;
        memset(v,0,sizeof(v));
        memset(ts,0,sizeof(ts));
        for(int i=1;i<=m;i++){
            cin>>num;
            scanf("%d:%d",&mins,&secs);
            cin>>st;
            if(v[num]){
                continue;
            }
            if(st=="AC"){
                ts[num] += mins*60 + secs;
                v[num]=1;
            } else {
                ts[num] += 20;
            }
        }
        for(int i=1001;i<=1000+n;i++){
            if(v[i]){
                tot++;
                ans += ts[i];
            }
        }
        cout<<tot<<" "<<ans<<endl;
    }
    return 0;
}

Building Shops

Problem Description
HDU’s n classrooms are on a line ,which can be considered as a number line. Each classroom has a coordinate. Now Little Q wants to build several candy shops in these n classrooms.

The total cost consists of two parts. Building a candy shop at classroom i would have some cost ci. For every classroom P without any candy shop, then the distance between P and the rightmost classroom with a candy shop on P’s left side would be included in the cost too. Obviously, if there is a classroom without any candy shop, there must be a candy shop on its left side.

Now Little Q wants to know how to build the candy shops with the minimal cost. Please write a program to help him.

给n个坐标,每个点可以选择建或者不建,建的话,就花费该点的权值,不建的话到左边的最右的有小店的坐标点,代价为距离之差。
dp.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> 

#define ll long long

using namespace std;

ll f[3005];
ll dis[3005];

struct node{
    ll x,cost;
}A[3005];

bool cmp(node a, node b){
    return a.x<b.x;
}

int main() {
    int n;
    while (cin >> n) {
        for(int i = 0; i < n; i++)
            cin>>A[i].x>>A[i].cost;
        sort(A, A+n, cmp);
        dis[0]=0;
        A[n].cost=0;
        A[n].x=A[0].x;
        for(int i=1;i<=n;i++)
            dis[i]=dis[i-1]+A[i].x-A[0].x;
        f[0]=A[0].cost;
        for(int i=1;i<=n;i++){
            f[i]=f[i-1]+A[i].cost;
            for(int j=0;j<i;j++){
                ll res=dis[i-1] - dis[j] - (i-j-1) * (A[j].x-A[0].x);
                f[i]=min(f[i], f[j] + res + A[i].cost);
            }
        }
        cout<<f[n]<<endl;
    }
    return 0;
}

Coprime Sequence

Problem Description
Do you know what is called “Coprime Sequence”? That is a sequence consists of n positive integers, and the GCD (Greatest Common Divisor) of them is equal to 1.
“Coprime Sequence” is easy to find because of its restriction. But we can try to maximize the GCD of these integers by removing exactly one integer. Now given a sequence, please maximize the GCD of its elements.

删去一个数,是的所有数的共同gcd最大。

dp.

f[i][0..1][0..1] 第i个 0删去/1保留 已经删去0..1次。
传递关系见程序。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int a[111111];
int f[111111][2][2];

int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}

int main(){
    int T,n;
    cin>>T;
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        memset(f,0,sizeof(f));
        f[1][0][0] = a[1];
        f[1][1][1] = 0;
        for(int i=2;i<=n;i++){
            f[i][1][1] = f[i-1][0][0];
            f[i][0][0] = gcd(f[i-1][0][0] , a[i]);
            f[i][0][1] = max(gcd(f[i-1][1][1] , a[i]) , gcd(f[i-1][0][1] , a[i]));
        }
        int ans = max(f[n][1][1] , f[n][0][1]);
        cout<<ans<<endl;
    }
    return 0;
}

Deleting Edges

Problem Description
Little Q is crazy about graph theory, and now he creates a game about graphs and trees.
There is a bi-directional graph with n nodes, labeled from 0 to n−1. Every edge has its length, which is a positive integer ranged from 1 to 9.
Now, Little Q wants to delete some edges (or delete nothing) in the graph to get a new graph, which satisfies the following requirements:
(1) The new graph is a tree with n−1 edges.
(2) For every vertice v(0< v < n), the distance between 0 and v on the tree is equal to the length of shortest path from 0 to v in the original graph.
Little Q wonders the number of ways to delete edges to get such a satisfied graph. If there exists an edge between two nodes i and j, while in another graph there isn’t such edge, then we regard the two graphs different.
Since the answer may be very large, please print the answer modulo 1e9+7.

删除一些边使得这张图形成一个树,并且树上的所有点到根的距离都是原图中的最短距离。

1.先floyd做出最短路。
2.然后统计 dist[1..i] = dist[1..k] + dist[k..i] 的 k 的个数。
3.乘法原理算出。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

#define LL long long

using namespace std;

const LL MOD = 1e9+7;
const int INF = 1000000;

int mp[111][111];
int g[111][111];
int n;
char ch;
LL a[111];

int main(){
    while(cin>>n){
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                cin>>ch;
                mp[i][j] = ch - '0';
                g[i][j] = ch - '0';
                if(mp[i][j] == 0 && i-j){
                    mp[i][j] = INF;
                }
            }
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if( mp[i][k] + mp[k][j] < mp[i][j] ){
                        mp[i][j] = mp[i][k] + mp[k][j];
                    }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(i==j) continue;
                if(g[i][j]==0) continue;
                if(mp[1][i] + g[i][j] == mp[1][j]){
                    a[j]++;
                }
            }
        LL ans = 1;
        for(int i=1;i<=n;i++){
            if(a[i]==0) a[i]=1;
            ans = ans * a[i] % MOD;
        }
        cout<<ans % MOD<<endl; 
    }
    return 0;
}

Easy Summation

计算题。

#include <cstdio>
#include <cstring>
#include <iostream>

#define LL long long

using namespace std;

const LL MOD = 1e9 + 7;

LL pow(LL a,LL n){
    LL res = 1LL;
    for(int i=1;i<=n;i++) res = res * a % MOD;
    return res; 
}

int main(){
    int T;
    cin>>T;
    LL n,k,ans;
    while(T--){
        ans = 0;
        cin>>n>>k;
        for(LL i=1;i<=n;i++)
            ans = (ans + pow(i,k) )% MOD;
        cout<<ans<<endl;
    }
    return 0;
} 

Graph Theory

Problem Description
Little Q loves playing with different kinds of graphs very much. One day he thought about an interesting category of graphs called “Cool Graph”, which are generated in the following way:
Let the set of vertices be {1, 2, 3, …, n}. You have to consider every vertice from left to right (i.e. from vertice 2 to n). At vertice i, you must make one of the following two decisions:
(1) Add edges between this vertex and all the previous vertices (i.e. from vertex 1 to i−1).
(2) Not add any edge between this vertex and any of the previous vertices.
In the mathematical discipline of graph theory, a matching in a graph is a set of edges without common vertices. A perfect matching is a matching that each vertice is covered by an edge in the set.
Now Little Q is interested in checking whether a ”Cool Graph” has perfect matching. Please write a program to help him.

每个点有个状态,1表示跟前面所有点连边,2表示无操作。

判断是否能形成“cool graph”。

所谓cool graph就是每个点都配上对。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int main(){
    int T,n,a;
    cin>>T;
    while(T--){
        cin>>n;
        int cnt = 1;
        for(int i=2;i<=n;i++){
            cin>>a;
            if(a == 2 || cnt == 0){
                cnt++;
            } else {
                cnt--;
            }
        }
        if(cnt) puts("No");
        else puts("Yes");
    } 

    return 0;
} 

Happy Necklace

一串项链可以染成红蓝色,要求连续 (素数) 项中红色大于等于蓝色。

做法:不会。
dfs打表找规律。

f[n] = f[n-1] + f[n-3]

#include<cstdio> 
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
const ll P = 1e9+7;
const int N=3;
ll n,m;

struct matrix{
    ll a[N][N];
    int row,col;
    matrix():row(N),col(N){memset(a,0,sizeof(a));}
    matrix(int x,int y):row(x),col(y){memset(a,0,sizeof(a));}
    ll* operator [] (int x){return a[x];}
    matrix operator * (matrix x){
        matrix tmp ;
        for (int i=0;i<=n;i++)
            for (int j=0;j<=n;j++){
                tmp[i][j]=0;
                for (int k=0;k<=n;k++)
                    tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j])%P;
            }
        return tmp;
    }
    void operator *= (matrix x){*this = *this * x;}
    matrix operator ^ (ll x){
        matrix ret;
        for (int i=0;i<=n;i++)ret[i][i]=1;
        matrix tmp = *this;
        for (;x;x>>=1,tmp*=tmp){if(x&1)ret *=tmp;}
        return ret;
    }
};

int main(){
    int T;
    cin>>T;
    ll x;
    while(T--){
        n = 2;
        scanf("%lld",&x);
        matrix tmp;
        tmp[0][0]=tmp[0][2]=tmp[1][0]=tmp[2][1]=1;
        tmp = tmp^(x-2);
        ll ans = (tmp[0][0] * 3 + tmp[0][1] * 2 + tmp[0][2]  ) % P;
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值