题目链接:http://codeforces.com/contest/417
这可能是算很简单的一场CF了。
A题:大意是要让一些人进决赛, 有两种方式一种是C道题,晋级n个人, 还有一种是d道题, 晋级1个人, 现在给出要晋级的人数, 求最少需要多少道题目。 计算几种可能的情况, 比较一下即可。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int c, d, m, n, k;
int main(){
scanf("%d%d%d%d%d", &c, &d, &n, &m, &k);
int x, y;
int res = (m*n) - k;
if(res < 0) res = 0;
x = res*d;
y = res/n * c;
if(res % n != 0){
int n1 = y + c;
int n2 = y + (res%n) * d;
y = n1 < n2 ? n1 : n2;
}
printf("%d\n", x < y? x : y);
return 0;
}
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int main(){
int n;
scanf("%d", &n);
bool suc = 1;
memset(a, -1, sizeof(a));
while(n--){
int x, k;
scanf("%d%d", &x, &k);
if(suc == 0) continue;
if(x == 0 && a[k] == -1) a[k] = 0;
else{
if(x <= a[k]) continue;
else if(x == a[k] + 1) a[k] = x;
else suc = 0;
}
}
if(suc) printf("YES\n");
else printf("NO\n");
return 0;
}
C题:一个简单的构造题。 题意是:有n个球队互相踢比赛, 每两个球队之间最多踢一场比赛, 现在已知每支球队都踢了K场比赛, 构造一种可能的情况。 首先N支球队最多踢n*(n-1)/2场比赛, 先预判断一下n*k是否超过这个数字。
如果没超过我们可以这样构造: 球队1与2,3...踢, 球队2与3,4...踢,...... 球队n与1,2..踢,依此构造。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int main(){
int n, k;
scanf("%d%d", &n, &k);
int t = n*(n-1)/2;
if(n*k > t) printf("-1\n");
else{
printf("%d\n", n*k);
for(int i = 1; i <= n; ++i){
for(int j = i + 1; j <= i + k; ++j){
printf("%d %d\n", i, (j-1)%n + 1);
}
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = (1<<20) | 0x10;
const LL INF = ((LL)1 << 60);
LL f[N];
int n, m;
LL b;
struct node{
int x, n;
int slo;
}a[110];
bool cmp(node a, node b){
return a.n < b.n;
}
int main(){
scanf("%d%d%I64d", &n, &m, &b);
for(int i = 0; i < n; ++i){
int x, k, t;
scanf("%d%d%d", &a[i].x, &a[i].n, &t);
for(int j = 0; j < t; ++j){
int num;
scanf("%d", &num);
a[i].slo |= 1 << (num - 1);
}
}
sort(a, a + n, cmp);
// memset(f, INF, sizeof(INF));
for(int i = 1; i < (1<<m); ++i){
f[i] = INF;
}
LL ans = INF;
for(int i = 0; i < n; ++i){
for(int j = 0; j < (1<<m); ++j){
LL tmp = (LL)a[i].x + f[j];
if(tmp < f[j|a[i].slo])
f[j|a[i].slo] = tmp;
}
if(ans > f[(1 << m) - 1] + a[i].n * b)
ans = f[(1 << m) - 1] + a[i].n * b;
}
if(ans == INF) ans = -1;
printf("%lld\n", ans);
return 0;
}
E题:看了别人的思路。 同样是一道构造题。用到了矩阵的知识。 给出m, n 要求构造出一个矩阵满足, 每一行每一列的数平方和都是一个完全平方数。 思路很巧。 考虑到m*1和1*n的两个矩阵, 假如这两个矩阵都满足平方和为完全平方数的话, 那么这两个矩阵的乘积就是一个满足条件的矩阵(自己试试看)。问题转化为给出一个n,如何构造n个数使他们的平方和为完全平方数。 考虑这个等式:(n-1)+ (n/2 - 1)^2 = (n/2)^2; 由此可知, 在n等于偶数的情况下,n-1个1 和 一个 (n/2-1)可以构造成功。 如果n是奇数如何解决?可以将其中的一个1变成2,那么通过调整之后可以知道(n+1)/2 , 2, n-2满足条件。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N = 110;
int a[N], b[N];
void gao(int n, int *a){
if(n == 1) a[0] = 1;
else if(n == 2){
a[0] = 3;
a[1] = 4;
}
else{
if(n & 1){
for(int i = 0; i < n - 2; ++i) a[i] = 1;
a[n-2] = 2;
a[n-1] = (n >> 1) + 1;
}
else{
for(int i = 0; i < n - 1; ++i) a[i] = 1;
a[n-1] = (n >> 1) - 1;
}
}
}
int main(){
int n, m;
scanf("%d%d", &m, &n);
gao(m, a);
gao(n, b);
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j)
printf("%d ", a[i]*b[j]);
printf("\n");
}
return 0;
}