codeforces RCC2014 Warmup div2 A+B+C+D+E

来源:互联网 发布:幻灯片制作软件下载 编辑:程序博客网 时间:2024/05/18 19:20

链接:http://codeforces.com/contest/417

A:

题意:要选出至少n*m个人进到决赛里,现在有两种比赛方式,一种是主比赛,出c道题,可以选出n个人,另一种是附加比赛,出d道题,只选出1个人。同时还有k个人是固定已经进入决赛的人,问最少要出多少道题,才可以达到目标。

思路:发现现在还需要进决赛的人数是n*m-k。如果n*m-k<0,输出0,否则就要考虑用哪种方式更合适:可以计算一下两种方式下平均选出一个人需要的题数,一个是c/n,另一个就是d。两者大小不同则需判断,具体看代码吧。。

#include<cstdio>#include<algorithm>#include<iostream>#include<string>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<stack>#include<functional>using namespace std;#define maxn 3005int main(){    int c,d;    cin>>c>>d;    int n,m;    cin>>n>>m;    int k;      cin>>k;    int p = n*m-k;    if(p <= 0)cout<<'0'<<endl;    else{        int ans = m*c;        int tmp = 0;        double a1,a2;        a1 = c*1.0/n;        a2 = d*1.0;        if(a1 > a2)ans = d * p;        else{            tmp = p/n;            ans = tmp * c;            int x = p%n;            ans += min(c,d*x);        }        cout<<ans<<endl;    }    return 0;}

B:

题意:给你n个提交,每次提交有两个参数:k表示第几个人,x 表示这是第k个人交的第x份不同代码。要求交第x份代码的时候,机器要保存之前的代码。

思路:用一个数组a[i]表示第i个人现在交的最后一份不同的代码的编号,判断之后此人交的代码会不会超出范围即可。

#include<cstdio>#include<algorithm>#include<iostream>#include<string>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<stack>#include<functional>using namespace std;#define maxn 100005int a[maxn];int main(){    //while(1){        int n;cin>>n;        int x,k,flag = 1;        memset(a,-1,sizeof(a));        for (int i = 0; i < n; i++)        {            cin>>x>>k;            if(x == 0 && a[k] == -1)a[k] = 0;            else{                if(a[k] == x-1)a[k]=x;                else if(a[k] >= x)continue;                else flag = 0;            }        }        puts(flag==0?"NO":"YES");   // }    return 0;}

C:

题意:给你n个球队,要求你安排比赛,使得每个球队恰好赢得k场,两个球队间不能打多余一场比赛,输出一种可以的安排方案。

思路:考虑如果可以安排,那么至少需要n*k场不同的比赛,再考虑n个队,不重复的比赛一共有n*(n-1)/2场,所以先判断二者的大小,如果可以成立,就按照 1--2,3   2--3,4.。。。的方式构造就可以了。

#include<cstdio>#include<algorithm>#include<iostream>#include<string>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<stack>#include<functional>using namespace std;#define maxn 100005int a[maxn];int main(){    //while(1){        int n,k;cin>>n>>k;        int mm = (n-1)/2;        if(k > mm)cout<<-1<<endl;        else{            printf("%d\n",n*k);            for (int i = 1; i <= n; i++)            {                for (int j = 1; j <= k; j++)                {                    printf("%d %d\n",i,(i+j)>n?(i+j-n):(i+j));                }            }        }    //}    return 0;}

D:

题意:n个朋友,m道题,每个显示屏的钱b,每个朋友需要x元钱,已有k个显示屏,能做出mi个题,要求完成所有题的最小花费。

思路:因为m<=20,状压dp。但是需要注意的是这里多了一个显示屏的状态,可以把朋友给排一下序,按照需要已有的显示屏数,就可以保证取后面的朋友时,前面的显示屏要求可以被满足。

#include<cstdio>#include<algorithm>#include<iostream>#include<string>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<stack>#include<functional>using namespace std;#define N 105#define MAXN (1ll<<60)using namespace std;struct node{    int x,k,op;}a[N];long long f[1050000]={};bool cmp(node a,node b){    return a.k<b.k;}int main(){    int n,m,mi,x;    long long b;    long long ans=MAXN;    cin >> n >> m >> b;    for (int i=0;i<n;i++)    {        scanf("%d%d%d",&a[i].x,&a[i].k,&mi);        for (int j=0;j<mi;j++)        {            scanf("%d",&x);            a[i].op |= (1<<(x-1));        }    }    sort(a,a+n,cmp);    for (int i=1;i<1<<m;i++) f[i]=MAXN;    for (int i=0;i<n;i++)    {        for (int j=0;j<(1<<m);j++)        {            long long v=a[i].x+f[j];            f[j|a[i].op]=min(f[j|a[i].op],v);        }        ans=min(ans,a[i].k*b+f[(1<<m)-1]);    }    cout << (ans==MAXN?-1:ans)<< endl;    return 0;}

E:

题意:输入n,m 要求构造一个n*m的矩阵,使得每一行每一列数字的平方和也都是一个平方数。

思路:考虑如果现在已经有 n个数的平方和是平方数,和m个数的平方和也是平方数,会发现可以构造一个n*1和1*m的矩阵相乘就可以得到一个n*m的矩阵使条件成立。

关键是如何构造一个n个数的平方和是平方数。可以用(x+1)^2 = x^2+2*x+1 = x^2 + x + (x+1)。那么假如n是偶数(大于2),就可以构造x=n/2-1;这n个数就是n-1个1和1个x,

也就是(n-1 = x + x+1)个1 ,加上x,n个数就可以满足要求。如果n是奇数(大于1)怎么办呢?把上述方法中其中一个1变成2,那么平方和就会多3(=2*2-1).就又可以构造x=n/2+1;这n个数就是n-2个1,1个2和1个x。

思路二:前n-1个都是2,最后一个数是n-2即可。

证明:(n-1)*2^2 + (n-2)^2 = 4n-4+n^2-4n+4 = n^2. 【代码略】

注意:n等于1,2的时候特判。

代码:

#include<iostream>using namespace std;int a[105],b[105];void make(int x,int c[]){if(x & 1){if(x >= 2){for (int i = 0; i < x-2; i++){c[i] = 1;}c[x-2] = 2;}c[x-1] = x/2+1;}else{if(x>2){for (int i = 0; i < x-1; i++){c[i] = 1;}c[x-1] = x/2-1;}else{c[0] = 3;c[1] = 4;}}}int main(){int n,m;while(cin>>n>>m){make(n,a);make(m,b);for (int i = 0; i < n; i++){int f = 0;for (int j = 0; j < m; j++){if(f)cout<<' ';else f = 1;cout<<a[i]*b[j];}cout<<endl;}}return 0;}



0 0
原创粉丝点击