大学生程序设计邀请赛(华东师范大学网赛)

来源:互联网 发布:东东数据能刷枪吗? 编辑:程序博客网 时间:2024/04/29 06:17

地址

昨晚的比赛,最近都没怎么写过题了,本来打算拿这个练练手的,结果打到一半被琐事缠身啊。。。所以只写了四题就撤退了,然后今天来补个题。

A. 拼音魔法

Time limit per test: 1.0 seconds

Time limit all tests: 1.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 341 / 2134

魔法学校小学一年级有一种题。就是给一个字的拼音,给一个声调,让你正确地注音。但魔法老师给了巨量的题,你不用魔法根本不可能做完。所以现在要让你发明一种魔法完成这个任务。

问题已经讲完了,下面开始教授汉语。(会汉语或者自认为会汉语的可以自动跳过)

汉语中一个字的拼音由声母和韵母两部分组成,在极少数情况下也会没有声母,但一定有韵母。

一般认为,声母有 b, p, m, f, d, t, l, n, g, k, h, j, q, x, z, c, s, zh, ch, sh, r, y, w;韵母有:a, e, o, i, u, ü, ai, ei, ui, ao, ou, iu, ie, üe, er, an, en, in, un, ün, ang, eng, ing, ong。

不是所有的字母都能组合的,组合的时候有时会发生一些神奇的事情,例如 üe 变成了 ue。但是标调规则有如下口诀:

有 a 先找 a,没 a 找 o e,i u 并排标在后,这样标调不会错。

只有下面列出的元素可能会被标调。请按照下表输出(尤其注意 a 不要输出成 ɑ 了):

  • 第一声:ā ē ī ō ū ǖ。
  • 第二声:á é í ó ú ǘ。
  • 第三声:ǎ ě ǐ ǒ ǔ ǚ。
  • 第四声:à è ì ò ù ǜ。
  • 轻声:a e i o u ü。

辅助材料:由教育部公布的拼音方案。如果有描述不一致的地方,请以本题描述为准。

Input

第一行一个整数 T (1T105)

下面 T 行,每行一个拼音:拼音声调在各个拼音之后,用数字 [1-4] 进行表示。例如 zhong1 guo2。没有数字的说明是轻声,不用标调。

按照国际惯例,输入文件全部由 ASCII 编码组成。ü 用 v 来代替。但在输出中,应仍然用 ü 来表示。

Output

对于每一组数据,输出 Case x: y。其中 x 是从 1 开始的测试数据编号,y 是一个拼音标调后的答案。

注意:对于非 ASCII 字符的输出,请使用 UTF-8 编码。

Examples

input
5zhong1guo2meque1nv3
output
Case 1: zhōngCase 2: guóCase 3: meCase 4: quēCase 5: nǚ

Note

会 C/C++ 的魔法师最可爱了。

根据题意照做就好了,特殊字符直接用字符串存,也不用考虑那些乱七八糟的情况,简单想就行了,1A
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, int> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e5 + 10;const int M = 1e5;const double eps = 1e-8;int T, n, m, cas=1;char t[N];string s[N];string S[5][6];void solve(){int len = strlen(t),g = 0;if (t[len - 1] >= '1'&&t[len - 1] <= '4') g = t[len - 1] - '0', len--;for (int i = 0; i < len; i++) s[i] = t[i];for (int i = 0; i < len; i++){if (s[i] == "v") s[i] = "ü";}for (int i = 0; i < len; i++){if (s[i] == "a") {s[i] = S[g][0];for (int j = 0; j < len; j++) cout << s[j];return;}}for (int i = 0; i < len; i++){if (s[i] == "o") {s[i] = S[g][3];for (int j = 0; j < len; j++) cout << s[j];return;}}for (int i = 0; i < len; i++){if (s[i] == "e") {s[i] = S[g][1];for (int j = 0; j < len; j++) cout << s[j];return;}}int cnt = 0;for (int i = 0; i < len; i++){if (s[i] == "u" || s[i] == "i") cnt++;}if (cnt < 2) {for (int i = 0; i < len; i++){if (s[i] == "u") {s[i] = S[g][4];for (int j = 0; j < len; j++) cout << s[j];return;}}for (int i = 0; i < len; i++){if (s[i] == "i") {s[i] = S[g][2];for (int j = 0; j < len; j++) cout << s[j];return;}}for (int i = 0; i < len; i++){if (s[i] == "ü") {s[i] = S[g][5];for (int j = 0; j < len; j++) cout << s[j];return;}}}else {for (int i = 0; i < len; i++){if (s[i] == "u" || s[i] == "i"){--cnt;if (!cnt) {if (s[i] == "i") s[i] = S[g][2];else s[i] = S[g][4];for (int j = 0; j < len; j++) cout << s[j];return;}}}}}int gcd(int x, int y) { return x%y ? gcd(y, x%y) : y; }int main(){S[1][0] = "ā"; S[1][1] = "ē"; S[1][2] = "ī"; S[1][3] = "ō"; S[1][4] = "ū"; S[1][5] = "ǖ";S[2][0] = "á"; S[2][1] = "é"; S[2][2] = "í"; S[2][3] = "ó"; S[2][4] = "ú"; S[2][5] = "ǘ";S[3][0] = "ǎ"; S[3][1] = "ě"; S[3][2] = "ǐ"; S[3][3] = "ǒ"; S[3][4] = "ǔ"; S[3][5] = "ǚ";S[4][0] = "à"; S[4][1] = "è"; S[4][2] = "ì"; S[4][3] = "ò"; S[4][4] = "ù"; S[4][5] = "ǜ";S[0][0] = "a"; S[0][1] = "e"; S[0][2] = "i"; S[0][3] = "o"; S[0][4] = "u"; S[0][5] = "ü";//for (int i = 0; i < 5; i++) cout << S[i] << endl;for (inone(T); T--;cas++) {scanf("%s", t);printf("Case %d: ", cas);solve();putchar(10);}return 0;}

B. 分词

Time limit per test: 1.0 seconds

Time limit all tests: 1.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 40 / 381

有一句句子因为粘贴的时候出现了一点问题空格全部丢失了。现在给一本字典,每个词都对应这个词出现的频率(每十亿)。根据这个频率,我们可以根据下面的公式算出这个词带来的收益 P(word)

P(word)=len2(word)ln(frequency(word))

其中 frequency 就是上面所提到的频率。len 指的是单词的长度。

特别的,对于字典中没有出现过的词,P(word)=0

请对句子进行适当的分割,使得分割得到的所有词收益之和最大。同一个词可以重复出现,收益算作多次。

Input

先给出一本词典,词典的第一行是词条数(词条数约为 40 000),下面每行分别是单词和对应出现频率,用空格隔开。单词中只会出现英文字母大小写,不会有多余的空格。每个单词只会出现一次。频率是一个正实数

所有单词长度之和不超过 3105,最长单词长度不超过 30

接下来一行一个整数 T (T10),表示有 T 个查询。

下面 T 行,每行一个句子,句子长度不超过 5 000。句子中保证只含有英文字母大小写。注意单词匹配时,不区分大小写

词典数据来源于 Wikipedia Project Gutenberg(可能需要代理),其中 1-10000 词汇。

查询数据来源于 IELTS Test。

Output

对于每组数据,输出两行。

第一行是一个实数,表示最大能达到的收益。输出和答案相差不超过 103 即可认为正确。

第二行输出一连串单词,单词和单词之间用空格隔开。满足:

  • 把这些单词依次串联起来可以得到原句子;
  • 所有单词的收益值相加得到第一行的实数。

Examples

input
5ano 10ther 30another 10an 300other 201another
output
112.826670another
input
5ano 10.0ther 30.0another 10.0an 300.0other 2000.01another
output
212.837691an other

Note

样例给出的词典与测试数据有所不同。

一个套路题吧,之前就见过类似的了,处理方法是字典树优化dp,把词典弄成字典树,然后dp递推记录最优值就好了,没有的单词是0
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, double> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 2e5 + 10;const int M = 1e5;const double eps = 1e-6;int T, n, m, v[N];char s[N];int g[N][26], sz;double f[N], p[N];void get(int x){if (!x) return;get(v[x]);if (v[x]) printf(" ");for (int i = v[x] + 1; i <= x; i++) printf("%c", s[i]);}int main(){while (~scanf("%d", &n)){sz = 0; p[0] = 0;ms(g[0], 0);rep(i, 1, n){scanf("%s", s);int k = 0, len = strlen(s);for (int j = 0; s[j]; j++){int x = s[j] - (s[j] >= 'A'&&s[j] <= 'Z' ? 'A' : 'a');if (!g[k][x]) {g[k][x] = ++sz;ms(g[sz], 0); p[sz] = 0;}k = g[k][x];}scanf("%lf", &p[k]);p[k] = log(p[k])*len*len;}inone(m);rep(i, 1, m){scanf("%s", s + 1);ms(f, 0);int len = strlen(s + 1);for (int j = 1; s[j]; j++){int rt = 0;for (int k = 0; k < 30; k++){if (!s[j + k]) break;int x = s[j + k] - (s[j + k] >= 'A'&&s[j + k] <= 'Z' ? 'A' : 'a');if (g[rt][x]) {rt = g[rt][x];if (f[j + k] < f[j - 1] + p[rt]){f[j + k] = f[j - 1] + p[rt];v[j + k] = j - 1;}}else {if (f[j + k] < f[j - 1]){f[j + k] = f[j - 1];v[j + k] = j - 1;}break;}}}printf("%lf\n", f[len]);get(len);putchar(10);}}return 0;}

C. 袋鼠妈妈找孩子

Time limit per test: 1.5 seconds

Time limit all tests: 10.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 41 / 172

袋鼠妈妈找不到她的孩子了。她的孩子被怪兽抓走了。

袋鼠妈妈现在在地图的左上角,她的孩子在地图第 x 行第 y 列的位置。怪兽想和袋鼠妈妈玩一个游戏:他不想让袋鼠妈妈过快地找到她的孩子。袋鼠妈妈每秒钟可以向上下左右四个方向跳一格(如果没有墙阻拦的话),怪兽就要在一些格子中造墙,从而完成一个迷宫,使得袋鼠妈妈能够找到她的孩子,但最快不能小于 k 秒。

请设计这样一个迷宫。

Input

第一行两个整数 n,m (1n,m8),表示地图的总行数和总列数。

第二行三个整数 x,y,k (1xn,1ym,x+y>1)

Output

输出一个地图,应正好 n 行 m 列。

用 . 表示空地,用 * 表示墙。袋鼠妈妈所在的位置和孩子所在的位置用 . 表示。

数据保证有解。

Examples

input
2 61 3 4
output
.*.***......
想到过dfs,不过因为一开始过的人很少,所以没去尝试。
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, double> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 2e5 + 10;const int M = 1e5;const double eps = 1e-6;int T, n, m, x, y, limit;char s[10][10];int a[4] = { 1,-1,0,0 };int b[4] = { 0,0,1,-1 };bool dfs(int x, int y, int z){if (x == 1 && y == 1) return z >= limit;rep(i, 0, 3) {int X = x + a[i], Y = y + b[i];if (!X || !Y || X > n || Y > m || s[X][Y] != '*') continue;int cnt = 0;rep(j, 0, 3){int u = X + a[j], v = Y + b[j];if (s[u][v] == '.') cnt++;}if (cnt > 1) continue;s[X][Y] = '.';if (dfs(X, Y, z + 1)) return true;s[X][Y] = '*';}return false;}int main(){while (~intwo(n, m)){inthr(x, y, limit);ms(s, 0);rep(i, 1, n) rep(j, 1, m) s[i][j] = '*';s[x][y] = '.'; dfs(x, y, 0);rep(i, 1, n) puts(s[i] + 1);}return 0;}

D. 实验室传染病

Time limit per test: 2.0 seconds

Time limit all tests: 10.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 5 / 409

ECNU 的 ACM 实验室患上了一种传染病,这种病的传染性极强,并且因为每个人的体质不同传染的范围也不同。

为了简化这个问题,我们不妨假设有 n 个人站在一条水平线上,每个人有初始的位置和他患病时的传染范围。当一个人患病时,他的传染范围内(包括边界上)的人全部会被感染并继续向外传播。

但是我们并不知道 ECNU 实验室的传染源是谁,所以请你计算出每个人作为传染源时最后会使得多少人被感染?

Input

测试数据包含不超过 20 个测试文件,每个测试文件是单组数据。

第一行一个整数 n (1n105)

接下来 n 行每行有两个整数 xi,ri (109xi1091ri109),表示每个人的位置和传染范围。

数据保证位置各不相同。

Output

一行 n 个整数。其中第 i 个表示第 i 个人(按照输入顺序)作为传染源时最后被感染的人数。

Examples

input
40 108 318 1020 1
output
2 1 3 1
这题同样在之前某场比赛中见到过类似的题,可以直接暴力的考虑,对于可能从某个点左边影响其右边的情况,或者从右边回来的情况,其实是log级别的。
所以每次o(n)去递推每个点的最左和最右,然后再考虑左右影响log(n)次即可。
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, int> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 2e5 + 10;const int M = 1e5;const double eps = 1e-6;int T, n, l[N], r[N];pii a[N], b[N];void make(){stack<int> p;rep(i, 1, n){while (!p.empty() && p.top() >= l[i]){l[i] = min(l[i], l[p.top()]); p.pop();}p.push(i);}while (!p.empty()) p.pop();per(i, n, 1){while (!p.empty() && p.top() <= r[i]){r[i] = max(r[i], r[p.top()]); p.pop();}p.push(i);}while (!p.empty()) p.pop();}void reverse(){stack<int> p;rep(i, 1, n){while (!p.empty() && p.top() >= l[i]){r[i] = max(r[i], r[p.top()]); p.pop();}p.push(i);}while (!p.empty()) p.pop();per(i, n, 1){while (!p.empty() && p.top() <= r[i]){l[i] = min(l[i], l[p.top()]); p.pop();}p.push(i);}while (!p.empty()) p.pop();}bool cmp(int x, int y){return a[x] < a[y];}int main(){while (~inone(n)){rep(i, 1, n) intwo(a[i].ff, a[i].ss), b[i] = a[i];sort(a + 1, a + n + 1);rep(i, 1, n){l[i] = lower_bound(a + 1, a + n + 1, make_pair(a[i].ff - a[i].ss, 0)) - a;r[i] = lower_bound(a + 1, a + n + 1, make_pair(a[i].ff + a[i].ss, mod)) - a - 1;}rep(i, 1, 50){make();reverse();}rep(i, 1, n){int k = lower_bound(a + 1, a + n + 1, b[i]) - a;printf("%d%s", r[k] - l[k] + 1, i == n ? "\n" : " ");}}return 0;}

E. 黑心啤酒厂

Time limit per test: 1.0 seconds

Time limit all tests: 1.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 1184 / 4093

黑心啤酒厂为了让大家买啤酒,会把一瓶酒设计成恰好能倒七杯。由于聚会时经常会有大家一起干杯这样的事情,干杯之前又要给每个人都倒满,所以来两个人的时候,干完三轮,恰好多一杯;三个人的时候,干完两轮,恰好多一杯;四个人的时候会多三杯。在上述情况下,为了践行不浪费的原则,就会多买一瓶啤酒,再干一轮。当然多买的啤酒可能又有多了……然后循环往复,喝了好多好多。直到啤酒刚刚好喝完为止。

现在啤酒厂把酒瓶设计成刚好能倒 x 杯,请依次求出有 2 人、3 人,一直到 n 人参加聚会时,啤酒厂各能卖出多少瓶啤酒。

Input

输入只有一行,两个整数 x,n (1x109,2n105)

Output

输出 n1 行,分别表示 2,3,,n 人参加聚会时,能卖出的啤酒瓶数。

Examples

input
7 5
output
2345
这个没什么好说的,求gcd即可
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, int> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e5 + 10;const int M = 1e5;const double eps = 1e-8;int T, n, m, cas=1;int gcd(int x, int y) { return x%y ? gcd(y, x%y) : y; }int main(){scanf("%d%d", &m, &n);for (int i = 2; i <= n; i++){int g = gcd(i, m);printf("%d\n", i / g);}return 0;}

F. 丽娃河的狼人传说

Time limit per test: 1.0 seconds

Time limit all tests: 1.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 224 / 1759

丽娃河是华师大著名的风景线。但由于学校财政紧缺,丽娃河边的路灯年久失修,一到晚上就会出现走在河边要打着手电的情况,不仅非常不方便,而且影响安全:已经发生了大大小小的事故多起。

方便起见,丽娃河可以看成是从 1 到 n 的一条数轴。为了美观,路灯只能安装在整数点上,每个整数点只能安装一盏路灯。经专业勘测,有 m 个区间特别容易发生事故,所以至少要安装一定数量的路灯,

请问至少还要安装多少路灯。

Input

第一行一个整数 T (1T300),表示测试数据组数。

对于每组数据:

  • 第一行三个整数 n,m,k (1n103,1m103,1kn)

  • 第二行 k 个不同的整数用空格隔开,表示这些位置一开始就有路灯。

  • 接下来 m 行表示约束条件。第 i 行三个整数 li,ri,ti 表示:第 i 个区间 [li,ri] 至少要安装 ti 盏路灯 (1lirin,1tin)

Output

对于每组数据,输出 Case x: y。其中 x 表示测试数据编号(从 1 开始),y 表示至少要安装的路灯数目。如果无解,y 为 1

Examples

input
35 1 31 3 52 3 25 2 31 3 52 3 23 5 35 2 31 3 52 3 24 5 1
output
Case 1: 1Case 2: 2Case 3: 1

Note

因为今天不是满月,所以狼人没有出现。

贪心,策略是每次尽量往右边放,用数据结构什么的维护一下即可。
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, int> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e5 + 10;const int M = 1e5;const double eps = 1e-8;int T, n, m, k, q, cas = 1;int vis[N];int l[N], r[N], x[N], f[N];void add(int x){for (int i = x; i <= n; i += low(i)) f[i]++;}int sum(int x){int res = 0; for (int i = x; i; i -= low(i)) res += f[i]; return res;}int main(){for (inone(T); T--;cas++) {inthr(n, m, k);rep(i, 1, n) vis[i] = f[i] = 0;rep(i, 1, k) { inone(q); vis[q] = 1;}int flag = 1;rep(i, 1, m){inthr(l[i], r[i], x[i]);if (x[i] > r[i] - l[i] + 1) flag = 0;}if (!flag) { printf("Case %d: -1\n",cas); continue; }int cnt = 0;rep(i, 1, n){if (vis[i]) { add(i); continue; }rep(j, 1, m){if (l[j] <= i && i <= r[j]){if (sum(i) - sum(l[j] - 1) + r[j] - i < x[j]){add(i); cnt++; break;}}}}printf("Case %d: %d\n", cas, cnt);}return 0;}

G. 铁路修复计划

Time limit per test: 2.0 seconds

Time limit all tests: 15.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 146 / 1219

在 A 国有很多城际铁路。这些铁路都连接两个城市(城市从 1 到 n 编号),可以双向通行,使得任意两个城市之间都由铁路网联系起来。

不过在一次星球大战之后,所有的铁路都经历了不同程度的损伤以至于无法通行了。由于经费紧缺,A 国政府不愿意再出资造新的铁路。对于原有的城际铁路,根据铁路的实际情况,有以下两种处理办法:

  1. 使用国内技术进行修复:主要针对损坏情况不是很严重的铁路。国内公司会对铁路状况进行评估,然后如实开出铁路修复的费用。
  2. 使用国外技术进行修复:主要针对损坏情况严重的铁路。国外公司也会对铁路情况进行评估,然后按照铁路实际修复费用的 k倍来收费(其中 k 是一个由国外公司决定的实数,不管怎么说,优惠是不可能的,所以 k1)。

A国政府修复铁路的总预算是 M,目标是要让任意两个城市之间都能通过铁路联系起来。在预算不够且能够完成目标的条件下,显然没必要修复每一条铁路。

国外公司通过不知什么途径了解到了 A 国政府的总预算 M,他们现在要把 k 定下来,并且希望 k 尽可能得大。但 k 又不能太大,不然,如果 A 国政府发现无法完成任务的话,整个订单都会泡汤。

Input

测试数据包含不超过 30 个测试文件。每个测试文件是单个测试点。

第一行是三个整数 n,m,M (2n105,n1mmin{105,n(n1)2},1M1015)

接下来 m 行,每行四个整数 ui,vi,ti,fi。表示一条城际铁路,连接着 ui 和 vi 城市,ti 表示铁路实际修复费用。fi=1 表示只能由国外公司修复,fi=0 表示由国内公司修复。(1ui,vin,uivi,1ti106,fi{0,1})。输入保证两个城市之间不会存在多条铁路。

输入保证:

  • 在国外公司不乱收费 (k=1) 的情况下,使用预算能完成要求。
  • 完全不使用国外技术,只使用国内技术,是不能完成目标的。

Output

求 k 的最大值。输出答案与标准答案相差不超过 106 即判为正确。

Examples

input
3 3 91 2 1 11 3 2 02 3 1 1
output
7.000000
input
3 3 91 2 1 11 3 2 12 3 2 1
output
3.000000
如果k的值定下来,那就是最小生成树了,所以可以直接二分k,也可以迭代求解。
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, int> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e5 + 10;const int M = 1e5;const double eps = 1e-6;int T, n, m, cas = 1;long long val;int x[N], y[N], z[N], v[N], a[N], fa[N];double k;bool cmp(int t, int r){double a = z[t] ? k*v[t] : v[t];double b = z[r] ? k*v[r] : v[r];return a < b;}int get(int x) { return x == fa[x] ? x : fa[x] = get(fa[x]); }double make(){long long value = 0, cost = 0;sort(a + 1, a + m + 1, cmp);rep(i, 1, n) fa[i] = i;rep(i, 1, m){int fx = get(x[a[i]]), fy = get(y[a[i]]);if (fx == fy) continue;fa[fx] = fy; if (z[a[i]]) cost += v[a[i]];else value += v[a[i]];}return 1.0 * (val - value) / cost;}int main(){while (~scanf("%d%d%lld", &n, &m, &val)){rep(i, 1, m){infou(x[i], y[i], v[i], z[i]);a[i] = i;}k = 1;while (true){double bef = k;k = make();if (fabs(k - bef) < eps) break;}printf("%lf\n", k);}return 0;}

H. 法国传统舞蹈

Time limit per test: 1.0 seconds

Time limit all tests: 5.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 1 / 9

ECNU 的学生和老师都会跳法国传统舞蹈。

在舞会上,学生会穿着各种颜色的礼服,老师会穿着黑色的礼服,一起来跳法国传统舞蹈。所有的老师和学生在舞会一开始要按照规定的顺序(见输入解释)围成一个大圆,手拉着手,朝内。

在每一首舞曲(包括第一首)开始的时候,就要变换队形。变换队形可以有以下两种情况:

  1. 一个圆变成两个圆:一个圆从两个位置断开,然后各自结合为圆。在此过程中,除了在断开的位置有两个人的左手和两个人的右手会放开之外,其他的人的手还是紧紧地牵在一起。

  2. 两个圆变成一个圆:与 1 恰好相反。两个圆分别从两个位置断开,然后结合在一起。

注意:在变换后的队形中,所有人应该还是面朝内的。一个人也可以成一个圆,左手跟右手拉在一起就好了。(有点惨)

为了增加观赏性,规定舞会结束时,队形恰好又是一个大圆。并且大圆上的每个人的礼服颜色是预先规定的。假设大家都「足够配合」,那么演奏舞曲的乐手们至少要演奏多少支舞曲呢?

Input

第一行是三个整数 N,M,K (1N20,0M5,0K2000),分别表示参加舞会的学生数,老师数,和接下来的查询数量。

在舞会一开始,大圆一定可以表示成 1 2 3 ... N r r .. r(后面共有 M 个 r)。意思是说穿着礼服颜色为 1 的学生的右手边是颜色为 2 的学生,颜色为 2 的学生右手边是颜色为 3 的学生,以此类推,颜色为 N 的学生右边是一个老师。由于老师都穿着黑色礼服,所以都是 r,不作区分。最后一个 r 右手边是颜色为 1 的学生,围成一个圆。

接下来 K 行,表示的是舞会结束时规定的大圆的队形。每行恰好是 N+M 个整数或字母。队形的表示方法上面是相同的。由于跳舞的时候圆会旋转,所以圆从哪个人开始数其实是不影响的。

输入保证有解。

Output

对于每次查询,输出最少需要多少支舞曲。

Examples

input
5 0 11 2 4 3 5
output
2
input
7 5 26 7 r r r r r 1 2 3 4 56 7 r 1 2 3 4 r r r r 5
output
02

Note

样例 1:第一支舞曲开始时,3 和 4 之间,4 和 5 之间断开,变成 5 1 2 3 和 4(一个人)两个圆;第二支舞曲开始时,2 和 3 分开,4 的左右手分开,合并形成大圆,就能达到要求。

很巧妙的题,不容易想到,题解解释的比较清晰。先从环转为一个后继的序列,然后考虑变换对于序列的影响是交换两个位置的值。
于是乎,整个问题就转换为了从一个给定的序列到一个有序序列最少的交换次数了。
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, int> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 2e5 + 10;const int M = 1e5;const double eps = 1e-6;int T, n, m, vis[N];int a[N], b[N], c[N], d[N], e[N];char s[N];int main(){while (~inthr(n, m, T)){while (T--){rep(i, n + 1, n + m) c[i] = i;int cnt = n + 1;rep(i, 1, n + m){scanf("%s", s);if (s[0] == 'r') b[i] = cnt++;else sscanf(s, "%d", &b[i]);}int ans = INF;do {rep(i, 1, n + m) d[i] = b[i] <= n ? b[i] : c[b[i]];rep(i, 1, n + m) e[d[i]] = d[i % (n + m) + 1], vis[i] = 0;rep(i, 1, n + m){e[i] = (e[i] + n + m - 2) % (n + m) + 1;}int cnt = n + m;rep(i, 1, n + m){if (vis[i]) continue;vis[i] = 1; cnt--;for (int j = e[i]; j != i; j = e[j]) vis[j] = 1;}if (cnt & 1) continue;ans = min(ans, cnt);} while (next_permutation(c + n + 1, c + n + m + 1));printf("%d\n", ans);}}return 0;}

I. 七巧板

Time limit per test: 1.0 seconds

Time limit all tests: 3.0 seconds

Memory limit: 256 megabytes

Accept / Submit: 17 / 179

ECNU 的 ACM 队员经常在打比赛的时候玩七巧板。于是他们把 OJ 的图标都换成了七巧板……

这是一个有关七巧板的问题。今天,某一位队员在玩七巧板的过程中,不小心把七巧板散落在地。如果把地面看成是一个 xOy 平面,那么每块七巧板就可以看成是一个多边形。他现在知道了这些每个多边形的坐标,然后又故意地改错了一部分,想要考考擅长编程的你。

你只要回答他他给出的这些多边形是不是一副完整的七巧板就好了。

组成的七巧板一定要与下图的七巧板相似(形状相同,大小可以不相同)。

Input

输入包含多个测试文件,每个测试文件是单组数据。

每组数据给出 7 个多边形。每个多边形第一行是一个整数 n (3n4),表示这是一个几边形;接下来 n 行,每行两个实数,按顺序给出 (x1,y1),(x2,y2),,(xn,yn) (104xi,yi104)。点坐标按照逆时针方向给出,多边形是凸多边形。

输入精确到 1012,但只要点点距离、点边距离、边边距离不超过 104,就可以认为可以拼成。

数据保证有且仅有 7 个多边形。每个多边形的顶点数不超过 4

Output

如果可以拼成,输出 YES;否则,输出 NO

Examples

input
30.0 0.00.5 0.50.0 1.030.5 0.51.0 1.00.0 1.030.0 0.00.5 0.00.25 0.2540.5 0.00.75 0.250.5 0.50.25 0.2530.75 0.250.75 0.750.5 0.540.75 0.251.0 0.51.0 1.00.75 0.7530.5 0.01.0 0.01.0 0.5
output
YES
input
30.0 0.00.5 0.50.0 1.030.1 0.00.6 0.50.1 1.030.0 0.00.5 0.00.25 0.2540.5 0.00.75 0.250.5 0.50.25 0.2530.75 0.250.75 0.750.5 0.540.75 0.251.0 0.51.0 1.00.75 0.7530.5 0.01.0 0.01.0 0.5
output
YES
比较烦人的判断题,判断5个三角形和一个正方形一个平行四边形,需要注意细节,同时精度也要注意。
#include<map>     #include<set>    #include<ctime>      #include<cmath>     #include<stack>  #include<queue>       #include<string>      #include<vector>      #include<cstdio>          #include<cstring>        #include<iostream>      #include<algorithm>          #include<functional>      using namespace std;#define ms(x,y) memset(x,y,sizeof(x))          #define rep(i,j,k) for(int i=j;i<=k;i++)          #define per(i,j,k) for(int i=j;i>=k;i--)          #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])          #define inone(x) scanf("%d",&x)          #define intwo(x,y) scanf("%d%d",&x,&y)          #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)        #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)       #define lson x<<1,l,mid      #define rson x<<1|1,mid+1,r      #define mp(i,j) make_pair(i,j)      #define ff first      #define ss second      typedef long long LL;typedef pair<int, double> pii;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 2e5 + 10;const int M = 1e5;const double eps = 1e-6;int T, n, c3, c4;double f[N], z, l, r;double x[N], y[N], g[N];bool equels(double x, double y){return fabs(x - y) < eps;}bool check(){rep(i, 1, 7) {inone(n);if (n == 3){rep(j, 0, 2) scanf("%lf%lf", &x[j], &y[j]);rep(j, 0, 2) g[j] = (x[j] - x[(j + 1) % 3])*(x[j] - x[(j + 1) % 3]) + (y[j] - y[(j + 1) % 3])*(y[j] - y[(j + 1) % 3]);sort(g, g + 3);if (!equels(g[0], g[1]) || !equels(g[2], g[0] + g[1])) return false;f[c3++] = g[0];}else{c4++;rep(j, 0, 3) scanf("%lf%lf", &x[j], &y[j]);rep(j, 0, 3) g[j] = (x[j] - x[(j + 1) % 4])*(x[j] - x[(j + 1) % 4]) + (y[j] - y[(j + 1) % 4])*(y[j] - y[(j + 1) % 4]);sort(g, g + 4);if (equels(g[0], g[3])){if (!equels(g[0] + g[1], (x[0] - x[2])*(x[0] - x[2]) + (y[0] - y[2])*(y[0] - y[2]))) return false;z = g[0];}else if (equels(g[0] , g[1]) && equels(g[2] , g[3]) && equels(g[0] + g[1] , g[2])){double p = min((x[0] - x[2])*(x[0] - x[2]) + (y[0] - y[2])*(y[0] - y[2]),(x[1] - x[3])*(x[1] - x[3]) + (y[1] - y[3])*(y[1] - y[3]));if (!equels(p , g[0])) return false;l = g[0]; r = g[2];}else return false;}}if (c3 != 5 || c4 != 2) return false;sort(f, f + c3);if (!equels(f[0] , f[1]) || !equels(f[3] , f[4]) || !equels(f[2] , f[0] + f[1]) || !equels(f[3] , f[2] + f[2])) return false;if (!equels(f[0], z) || !equels(f[0] , l)) return false;return true;}int main(){puts(check() ? "YES" : "NO");return 0;}



0 0