第十一届北京邮电大学程序设计竞赛 - 热身赛 (1)

第十一届北京邮电大学程序设计竞赛 - 热身赛 (1)

注册新账号即可参加比赛(已被延长为3W分钟)

 

A.预处理筛出2^15以内的质数然后枚举计数即可

 1 #include <cstdio>
 2 
 3 int p[60000], v[60000];
 4 
 5 int main() {
 6     for(int i = 2;i <= 50000;i ++) {
 7         if(!v[i]) p[++ p[0]] = i;
 8         for(int j = 1;j <= p[0] && 1ll * i * p[j] <= 50000;j ++) {
 9              v[i * p[j]] = 1;
10              if(i % p[j] == 0) break;
11         }
12     }
13     int n, m;
14     while(scanf("%d", &n), n) {
15         m = 0;
16         for(int i = 2;i + i <= n;i ++)
17             if(!v[i] && ! v[n - i])
18                 m ++;
19         printf("%d\n", m);
20     }
21     return 0;
22 }
View Code

 

B.一个比较典型的背包问题

f[i]表示组成 i 元的方案数

然后分别用面值1 4 9 ... 289的coin更新17次就好了

 1 #include <cstdio>
 2 
 3 typedef long long ll;
 4 
 5 const ll Mod = 1000000009;
 6 
 7 int s[18];
 8 
 9 ll f[2222];
10 
11 int main() {
12     f[0] = 1;
13     for(int i = 1;i <= 17;i ++)
14         s[i] = i * i;
15     for(int j = 1;j <= 17;j ++)
16         for(int i = s[j];i <= 2000;i ++)
17             f[i] = (f[i] + f[i - s[j]]) % Mod;
18     int t, n;
19     scanf("%d", &t);
20     while(t --) {
21         scanf("%d", &n);
22         printf("%lld\n", f[n]);
23     }
24     return 0;
25 }
View Code

 

C.注意到题目描述最后一句

little Ding is concerned about the answer of every user's new friends

when that user is the only one who adds new friends

所以并不是并查集

直接枚举就好了,注意到为了防止一个人与自己建立新边并计入答案

我们一开始就设置好 i 和 i 自己是朋友即可

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

using namespace std;

vector <int> e[1010];

int t, m, n, p, f[1010];

int main() {
    cin >> t;
    while(t --) {
        cin >> n >> m;
        for(int i = 1;i <= n;i ++)
            f[i] = 0, e[i].clear();
        for(int u, v, i = 1;i <= m;i ++) {
            scanf("%d %d", &u, &v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        for(int i = 1;i <= n;i ++) {
            p = 0, f[i] = i;
            for(int j = 0;j < e[i].size();j ++)
                f[e[i][j]] = i;
            for(int j = 0;j < e[i].size();j ++)
                for(int u = e[i][j], k = 0;k < e[u].size();k ++)
                    if(f[e[u][k]] != i) f[e[u][k]] = i, p ++;
            printf("%d\n", p);
        }
    }
    return 0;
}
View Code

 

D.last[i]表示当 i 是选中的区间的最右端时,最左端可以在last[i] + 1的位置

pre[i]表示 ai 上一次出现的位置,初始化均为0

显然就有 last[i] = max(pre[j]), 1 <= j <= i

ans = max(i - last[i]). 1 <= i <= n

所以从左向右O(n)扫一遍即可

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 int t, n, l, a, m, p[100010];
 8 
 9 int main() {
10     cin >> t;
11     while(t --) {
12         m = 1, l = 0;
13         cin >> n;
14         memset(p, 0, sizeof p);
15         for(int i = 1;i <= n;i ++) {
16             scanf("%d", &a);
17             if(p[a]) l = max(l, p[a]);
18             p[a] = i, m = max(m, i - l);
19         }
20         cout << m << endl;
21     }
22     return 0;
23 } 
View Code

 

G.看样例xjb猜一下

分子是lcm,分母是gcd

然后就过了...

正确性简单证明:

要求n个分数的lcm

那么我们...嗨呀好麻烦自己脑补吧233

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 vector <ll> a, b;
 8 
 9 ll gcd(ll x, ll y) {
10     return y ? gcd(y, x % y) : x;
11 }
12 
13 int main() {
14     int n;
15     ll x, y, X, Y;
16     while(~scanf("%d", &n)) {
17         a.clear(), b.clear();
18         while(n --) {
19             scanf("%lld %lld", &x, &y);
20             a.push_back(x);
21             b.push_back(y);
22         }
23         X = a[0], Y = b[0];
24         for(int i = 1;i < a.size();i ++)
25             X = X / gcd(X, a[i]) * a[i], Y = gcd(Y, b[i]);
26         printf("%lld %lld\n", X, Y);
27     }
28     return 0;
29 }
View Code

 

posted @ 2017-04-01 17:00  ztztyyy  阅读(197)  评论(0编辑  收藏  举报