码迷,mamicode.com
首页 > 其他好文 > 详细

2016 年宁波工程学院第七届ACM校赛题解报告

时间:2016-05-10 18:27:54      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:

2016 年宁波工程学院第七届ACM校赛题解报告


 

本题解代码直接为比赛代码,仅供参考。

A,B,C,D,G,H,J,K,L,M 来自 Ticsmtc 同学.

F 来自 Gealo 同学.

E,I 来自Alex 学长.


 

Promblem A :    Two Sum

时间限制: 1 Sec  内存限制: 64 MB

 

题目描述:

 

给出n个数,另外给出?个整数S,判断是否可以从中取出2个数,使得这两个数的和是S。 

 

输入:

 

第?行有个整数T(1 <= T <= 10),代表数据组数。 对于每组数据,第?行包含两个整数n,S(2 <= n <= 103, 1 <= S <= 1000) 接下来?行包含n个整数,整数的?小在1到1000。 

 

输出:

 

对于每组数据,如果存在2个整数,和为S,则输出Yes,否则输出No。 

 

样例输入:

2

5 6

1 2 3 4 5

5 10

1 2 3 4 5

样例输出:

Yes

No

 

题解:

 

题目意思不难理解,我们控制两重循环枚举一下是哪两个数,然后用加法判断下是不是S,如果是就可以,如果枚举完了所有的都没有发现能等于S的,那么就是不行。

 

这里注意下,n个数,我们从下标零读入所有的数的话,那么外层循环i从0 ~ n- 1,考虑内层的时候,由于两个数不能够选重,所以内层循环 j 应当从 i + 1 ~ n - 1 ,然后看存储数字的save数组,save[i] + save[j] 是否等于 S 。

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <string>
 7 using namespace std;
 8  
 9 int save[10000];
10 int main(){
11     int t;
12     cin >> t;
13     while(t--){
14         int n;
15         int S;
16         cin >> n;
17         cin >> S;
18         for(int i = 0 ; i < n ; i++){
19             cin >> save[i];
20         }
21         ///
22         bool ok = 0;
23         for(int i = 0 ; i < n - 1 ; i++){
24             for(int j = i + 1 ; j < n ; j++){
25                 if(save[i] + save[j] == S){
26                     ok = 1; break;
27                 }
28             }
29         }
30         ////
31         if(ok) cout << "Yes" << endl;
32         else cout << "No" << endl;
33          
34     }
35     return 0;
36 }
View Code

 

 

 

 

Problem B : Poker

时间限制: 1 Sec  内存限制: 128 MB

 

题目描述:

 

很多牌中都有顺子,今天?小编给您5张牌,需要客官您判断下这5张牌能不能连成?把同花顺。

同花顺即花?一致的顺子,注意最?的顺子是A 2 3 4 5,最?的是10 J Q K A。 

 

输入:

第?行有?个整数T(1 <= T <= 30),代表数据组数。 每组数据包含5行,每?行包含牌的?值和花色

?值是{2 3 4 5 6 7 8 9 10 J Q K A}当中的一个, 花?是S(spade)、H(heart)、C(club)、D(diamond)其中之?。 

 

输出:

如果给定的牌可以组成同花顺,输出Yes;否则输出No。 

 

样例输入:

2

5 H

6 H

7 H

8 H

9 H

5 H

6 H

7 S

8 C

9 D

样例输出:

Yes

No

 

题解:

 

先解决读入问题,很多同学尝试用两个char 读入前后一个牌号一个花色,那么当牌号是10的时候,char 只读入一个字符,就会出现错误,其次,如果用scanf 方式读取字符,需要很小心的考虑空格和回车符,这些都会被当作字符读入。所以十分麻烦。

我采取的做法是读取字符串,然后转化回数字。

好的,接下来我们用到一个手牌数组,save[] , 假如花色没有不同的,save数组中存储所有牌面的数字。

这题的数字中的 A 比较特别, 既可以当作 1 看待 , 也可以当作 14 看待, 那么很有意思的事是当我们碰到A的时候转化成几。我选择了特判 A , 相当于把 1 和 14 都放进了手牌。

我们对手牌save数组排序,从小到大,然后判断一下连续的五张牌是不是都是递增且相差一,如果有A的话,要判断两遍,因为有A,相当于手牌数组中有六个数,可能由1 ~ 5 个数(A为1)是一个顺子,也可能由2 ~ 6 个数(A为14)是一个顺子。

然后就A掉了呐~。

 

代码:

 

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <string>
 7 using namespace std;
 8  
 9 int save[100010];
10  
11 int trans(string &in){
12     if(in.size() == 2){
13         return 10;
14     }
15     char k = in[0];
16     if(k >= 1 && k <= 9) return k - 0;
17     if(k == J) return 11;
18     if(k == Q) return 12;
19     if(k == K) return 13;
20 }
21  
22  
23 int main(){
24     int t;
25     cin >> t;
26     while(t--){
27         char color =  ;
28         bool ok = 1;
29         bool is_A = 0;
30         int p = 0;
31         for(int i = 0 ; i < 5 ; i++){
32             //cout << i << endl;
33             string temp; char c;
34             cin >> temp >> c;
35             //cout << temp << " " << c << endl;
36             if(color ==  ) color = c;
37             else if(color != c){
38                 ok = 0;
39             }
40             ///
41             if(temp == "A"){
42                 save[p++] = 1;
43                 save[p++] = 14;
44                 is_A = 1;
45             }
46             else save[p++] = trans(temp);
47         }
48         if(!ok) {printf("No\n"); continue;}
49         //
50         sort(save,save + p);
51         //
52         int pre = save[0];
53         for(int i = 1 ; i <= 4 ; i++){
54             if(save[i] != pre + 1){
55                 ok = 0; break;
56             }
57             pre = save[i];
58         }
59         //cout << "is A " << is_A << endl;
60         if(is_A && !ok){
61             ok = 1;
62             pre = save[1];
63             for(int i = 2 ; i <= 5 ; i++){
64                 if(save[i] != pre + 1){
65                     ok = 0; break;
66                 }
67                 pre = save[i];
68             }
69             //cout << "ok " << ok << endl;
70         }
71         ////
72         if(!ok) printf("No\n");
73         else printf("Yes\n");
74     }
75     return 0;
76 }
View Code

 

 

 

Problem C: I Need Minmum Number

时间限制: 1 Sec  内存限制: 64 MB

 

题目描述:

 

你有?个序列,一开始是空的,接下来执行n次操作,每次操作都是以下3种之?

 2 value 表示在序列末尾加?一个新的数

 1 表?删除序列末尾的那个数(此次操作在序列为空时不会出现)

 0 表?示询问当前序列?的最小值(此次操作在序列为空时不会出现) 

 

输入:

第?行有个整数T(1 <= T <= 10),代表数据组数。 对于每组数据,第?行包含?个整数n(1 <= n <= 105) 接下来包含n?,代表n次操作。 如果是一个整数0,代表询问当前序列?的最小值。 如果是一个整数1,代表删除序列末尾的那个数。

否则就是2 value,代表在序列末尾加入value(-10000 <= value <= 10000)。 

 

输出:

对于每个0操作,输出当前序列里的最小值。 

 

样例输入:

1

5

2 3

2 1

0

2 -1

0

样例输出:

1

-1

 

题解:

 

想用一个栈,和一个变量存储最小值,插入一个数就比较一下,询问的时候直接输出这个存储最小值变量,这样的同学太天真了。

问题是,还有弹出的操作,万一栈顶是最小值,你弹出了栈顶,然后你记录最小值的这个东西又要更新(你从哪里更新呢)。。。。

很多种做法,我的做法是设置两个数组,save数组模拟栈操作,minlist数组也是一个栈,纪录save栈中连续不增的子序列。那么得到以下规则:

1.插入一个数val时,val插入save栈末尾。如果val比minlist栈顶元素小或等于栈顶元素,那么将val插入minlist栈,如果val比minlist栈顶元素大,则不操作。说明save栈在插入val前还有比val小的数。

2.删除save栈顶的数时,首先删除这个栈顶数,其次比较下,这个栈顶数val,是不是等于minlist栈顶数,如果相等,同样将minlist栈顶删除。如果不等于,那么不做操作。

3.请求save栈中最小元素时,即为minlist的栈顶元素。

 

然后就A掉了呐~。

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 using namespace std;
 6  
 7 int save[100010];
 8 int minlist[100010];
 9  
10 int main(){
11     int t;
12     scanf("%d",&t);
13     while(t--){
14         int k;
15         scanf("%d",&k);
16         //
17         int pos = 0;
18         int minpos = 0;
19         //
20         for(int i = 0 ; i < k ; i++){
21             int op;
22             scanf("%d",&op);
23             if(op == 2){
24                 int val;
25                 scanf("%d",&val);
26                 save[pos++] = val;
27                 ///
28                 if(minpos == 0){
29                     minlist[minpos++] = val;
30                 }
31                 else if(val <= minlist[minpos - 1]){
32                     minlist[minpos++] = val;
33                 }
34             }
35             else if(op == 1){
36                 int temp = save[pos - 1];
37                 pos--;
38                 ////////
39                 if(temp == minlist[minpos - 1]){
40                     minpos--;
41                 }
42             }
43             else{
44                 printf("%d\n",minlist[minpos - 1]);
45             }
46         }
47     }
48     return 0;
49 }
View Code

 

 

Problem D : Two’s Complement

时间限制: 1 Sec  内存限制: 64 MB

题目描述:

现代大部分计算机都采用补码的形式存储有符号数,一个长度为w的补码b,

对应的十进制数字为:

技术分享

其中bi要么为1,要么为0。

例如,采用5位来表示时,-1的补码就是11111,现在告诉你一串补码,求出对应

的十进制下的数字。

 

 

输入:

第一行有一个整数T,代表数据组数(T <= 1000)。

每组数据输入只有一行,代表补码(长度小于等于30,大于等于1)。

 

 

输出:

对于每组数据,输出该补码对应的十进制数。

 

 

样例输入:

3

1001

10

001

样例输出:

-7

-2

1

 

题解:

 

嗯,其实这题需要知道二进制表示的一些知识,一个二进制数,我们从右到左叫做从低位到高位,那么我们从低位到高位的权值依次从2^0 , 2^1 , 2^2 ….. 

比如,二进制数 101

如何得到十进制数呢 , 从低位到高位,三位的权值分别为 2^0 , 2^1 , 2^2. 

那么他的十进制就是1 * 2^0 + 0 * 2^1 + 1 * 2^2.

 

 

好了,明白了低位高位和权值的概念,这题就已经可以做了。

这个数学公式的意思是:

 

-1  * 最高位上的数字 * 最高位上的权值 +(除去最高位后,次高位到最低位表示的这个二进制数。)

比如11111(5个1)是-1,是如何得到的呢?

首先我们发现最高位(也就是最左位)是1,权值是2^4,那么根据公式前一部分 , 计算出为-16.

除去了最高位剩下了1111(四个1)按照二进制计算为15。

那么两部分加起来就是-1啦。

 

读进来的时候用字符串,然后自己操作下权值就好?

A掉了哇~

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 using namespace std;
 6 char save[100010];
 7 int main(){
 8     int t;
 9     scanf("%d",&t);
10     while(t--){
11         scanf("%s",save);
12         int len = strlen(save);
13         int ans = 0;
14         long long quan = 1;
15         for(int i = len - 1; i >= 1 ; i--){
16             ans += (quan * (save[i] - 0));
17             quan*=2;
18         }
19         ans = ans + (-1) * (save[0] - 0) * quan;
20         cout << ans << endl;
21     }
22     return 0;
23 }
View Code

 

 

Problem E : Just Go

时间限制: 3 Sec  内存限制: 64 MB

题目描述:

There is a river, which contains n stones from left to right. These stones are magic, each

one has a magic number Ai which means if you stand on the ith stone, you can jump to (i +1)th stone, (i+2)th stone, ..., (i+Ai)th stone(when i+Ai > n, you can only reach as far as n), you want to calculate the number of ways to reach the nth stone.

Notice: you can not jump from right to left! 

 

 

输入:

Input starts with an integer T(1 <= T <= 10), denoting the number of test cases. Each test case contains an integer n(1 <= n <= 105), denoting the number stones. Next line contains n integers Ai(1 <= Ai <= 108). 

 

输出:

For each test case, print the number of way to reach the nth stone module 109+7. 

 

样例输入:

3

5

1 2 3 4 5

1

10

2

2 1

样例输出:

3

1

1

题解:

 

按照题目意思,模拟操作,套数据结构线段树。

 

代码:

技术分享
  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <math.h>
  4 using namespace std;
  5 
  6 const int N = 110010;
  7 const int mod = 1e9 + 7;
  8 
  9 struct SegTree {
 10     int l, r;
 11     int way;
 12     int add;
 13 }tree[N << 2];
 14 
 15 void modify(int &target, int val) {
 16     target += val;
 17     target = (target % mod + mod) % mod;
 18 }
 19 
 20 void pushup(int p) {
 21     modify(tree[p].way, (tree[p << 1].way + tree[p << 1 | 1].way) % mod);
 22 }
 23 
 24 void build(int p, int l, int r) {
 25     tree[p].l = l;
 26     tree[p].r = r;
 27     tree[p].add = tree[p].way = 0;
 28     if (l == r) {
 29         if (l == 1) {
 30             tree[p].way = 1;
 31         }
 32         return;
 33     }
 34     int mid = (l + r) >> 1;
 35     build(p << 1, l, mid);
 36     build(p << 1 | 1, mid + 1, r);
 37     pushup(p);
 38 }
 39 
 40 void pushdown(int p) {
 41     if (tree[p].add) {
 42         modify(tree[p << 1].add, tree[p].add);
 43         modify(tree[p << 1 | 1].add, tree[p].add);
 44         modify(tree[p << 1].way, tree[p].add);
 45         modify(tree[p << 1 | 1].way, tree[p].add);
 46         tree[p].add = 0;
 47     }
 48 }
 49 
 50 void update(int p, int l, int r, int val) {
 51     if (l <= tree[p].l && tree[p].r <= r) {
 52         modify(tree[p].add, val);
 53         modify(tree[p].way, val);
 54         return;
 55     }
 56     pushdown(p);
 57     int mid = (tree[p].l + tree[p].r) >> 1;
 58     if (r <= mid) {
 59         update(p << 1, l, r, val);
 60     }
 61     else if (l > mid) {
 62         update(p << 1 | 1, l, r, val);
 63     }
 64     else {
 65         update(p << 1, l, mid, val);
 66         update(p << 1 | 1, mid + 1, r, val);
 67     }
 68     pushup(p);
 69 }
 70 
 71 int query(int p, int pos) {
 72     if (tree[p].l == tree[p].r) {
 73         return tree[p].way;
 74     }
 75     pushdown(p);
 76     int mid = (tree[p].l + tree[p].r) >> 1;
 77     if (pos <= mid) {
 78         return query(p << 1, pos);
 79     }
 80     else {
 81         return query(p << 1 | 1, pos);
 82     }
 83 }
 84 
 85 int main() {
 86     int t;
 87     scanf("%d", &t);
 88     while (t--) {
 89         int n;
 90         scanf("%d", &n);
 91         int val;
 92         build(1, 1, n);
 93         for (int i = 1; i <= n; ++i) {
 94             scanf("%d", &val);
 95             int way = query(1, i);
 96             int s = i + 1;
 97             int e = min(n, i + val);
 98             if (i == n) {
 99                 continue;
100             }
101             update(1, s, e, way);
102         }
103         printf("%d\n", query(1, n));
104     }
105     return 0;
106 }
View Code

 

Problem F : Fat Brother’s new way

时间限制: 1 Sec  内存限制: 64 MB

题目描述:

I bet, except Fat Brothers, all of you don’t like strange way to show integers , he is really like this way to showing integers:

1 -> ‘A’

2 -> ‘B’

…….

26 -> ‘Z’

27 -> ‘AA’

28 -> ‘AB’

…….

Unfortunately, Fat Brother’s mathematics is poor, so he needs your help, he will give you some integers, and you must transform it with Fat Brother’s way.

 

 

输入:

Input starts with an integer T(T <= 10000), denoting the number of test case.

For each test case, an integers n(1 <= n <= 2147483647) is given.

 

 

输出:

For each case,  output the corresponding string with upper-case letters.

 

 

样例输入:

3

17311

2068

37

样例输出:

YOU

CAN

AK

题解:

先将26个字母存入0~25的数组中,第一步将n - 1对26取余,余数便是对应的字母所在的位置,接下来便是将n除以26直到0为止反复进行这一系列的操作。还有一些细节值得注意。

当n为52时,答案是AZ但只是按这种方法输出会是BZ由于52/26=2。所以在每次n%26=0时n/26

时要减一

 

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 char a[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 6 char b[100000];
 7 int main()
 8 {
 9     int t;
10     scanf("%d" , &t);
11     int n;
12     for(int i = 0 ; i < t ; i++)
13     {
14         scanf("%d" , &n);
15         int g = 0;
16         while(n > 0)
17         {
18             if(n % 26 != 0)
19                 b[g++] = a[n % 26 - 1];
20             else
21             {
22                 b[g++] = a[25];
23                 n--;
24             }
25             if(n == 26)
26                 break;
27             n /= 26;
28         }
29         for(int i = g - 1 ; i >= 0 ; i--)
30             printf("%c" , b[i]);
31         printf("\n");
32     }
33     return 0;
34 }
View Code

 

 

Problem G : Is The Same?

时间限制: 1 Sec  内存限制: 64 MB

题目描述:

 

给出2个字符串S和T,如果可以通过循环移位使得S和T相等,则我们称S和T是同构字符串, 例如S=“abcd”, T=“bcda”,则S和T是同构字符串;而S=“abcd”和T=“bcad”则不是同构字符串。

循环移位是指:在?个长度为n的字符串S中,取?个任意下标i,把字符串分为两段,分别为 S1S2...Si 和Si+1Si+2...Sn,然后把字符串变为Si+1Si+2...SnS1S2...Si,例如S=“qwerty”,取i=3, 则变 为”rtyqwe”(注意,一个字符串本?身也算是它的同构字符串)。 

 

输入:

第?行包含一个整数T(1 <= T <= 20),代表测试组数。

对于每组数据,包含2个字符串,字符串长度都小于等于105且非空,输入保证字符串只包含小写字?。 

 

输出:

 

对于每组数据,如果这两个字符串是同构字符串,则输出Yes,否则输出No。 

 

样例输入:

2

abcd

bcda

abcd

bcad

样例输出:

Yes

No

 

 

题解:

 

姑且算有点算法的水题吧,我们把第一个串叫做A串,第二个叫做B串,如果A串长度和B串都不一样,那么肯定不同构。

那么A串和B串长度相等时,我们继续。

好像有很多的思路,我的想法是将A串倍增两倍,比如A串是abcde,我倍增后A串为abcdeabcde,然后在倍增后的A串中找一下有没有B串就行了。找的到就是同构,找不到就不同构。

字符串匹配,套个KMP就稳稳的过掉了~

A掉了呐~

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 using namespace std;
 6 char A[300010];
 7 char B[300010];
 8 int Next[300010];
 9  
10 void check(){
11     int len = strlen(B);
12     for(int i = 0; i < len ; i++){
13         cout << Next[i] << " ";
14     }
15     cout << endl;
16     return ;
17 }
18  
19 void make_next(){
20     Next[0] = -1;
21     int len = strlen(B);
22     int i = 0, k = -1;
23     while(i < len){
24         if(k == -1 || B[i] == B[k]){
25             Next[++i] = ++k;
26         }
27         else k = Next[k];
28     }
29     return ;
30 }
31  
32 bool kmp(){
33     make_next();
34     int len1 = strlen(A);
35     int len2 = strlen(B);
36     ////
37     int i = 0 , k = 0;
38     while(i < len1 && k < len2){
39         if(k == -1 || A[i] == B[k]){i++; k++;}
40         else k = Next[k];
41     }
42     if(k == len2) return 1;
43     else return 0;
44 }
45  
46 int main(){
47     int t;
48     scanf("%d",&t);
49     while(t--){
50         scanf("%s",A);
51         scanf("%s",B);
52         int len = strlen(A);
53         //
54         if(len != strlen(B)) {printf("No\n"); continue;}
55         //
56         for(int i = 0 ; i < len ; i++){
57             A[len + i] = A[i];
58         }
59         A[2 * len - 1] = \0;
60          
61         bool ans = kmp();
62          
63         if(ans) printf("Yes\n");
64         else printf("No\n");
65     }
66     return 0;
67 }
View Code

 

 

 

Problem H : Party

时间限制: 2 Sec  内存限制: 64 MB

 

题目描述:

 

N students were invited to attend a party, every student has some friends, only if someone’s all friends attend this party, this one can attend the party(ofcourse if he/she has no friends, he/she also can attend it.), now i give the friendship between these students, you need to tell me whether all of them can attend the party.

Note that the friendship is not mature, for instance, if a is b’s friend, but b is not necessary a’s friend. 

 

输入:

 

Input starts with an integer T(1 <= T <= 10), denoting the number of test case.

For each test case, first line contains an integer N(1 <= N <= 100000), denoting the number of students.

Next n lines, each lines first contains an integer K, denoting the number of friends belong to student i(indexed from 1). Then following K integers, denoting the K friends.

You can assume that the number of friendship is no more than 100000, and the relation like student A is himself’s friend will not be existed. 

 

输出:

 

For each test case, if all of the students can attend the party, print Yes, otherwise print No. 

 

样例输入:

2

3

1 2

1 3

1 1

3

1 2

0

1 1

样例输出:

No

Yes

 

 

题解:

 

题目大意就是要邀请一堆人去玩,然后呢,有些人要某些人去才肯去,有些人呢,自己就会去。

题目给你N个人,告诉你依赖的关系,或者说这个人不依赖他人。问你能否所有的人都要到。

 

作为一个有向图,所有人都能到的条件应该就是不存在环,那么首先想到的是简单的用dfs判一下环,可是这里人数太多,用dfs能跑到明年,而且万一不是全部联通的,跑都跑不清楚了。所以改变思路。

先进行规定,如果A依赖B,我们说A到B有一条边(有向边A—>B)。

接下来:

1.建立这个有向图。

2.寻找出度为0的点,放进队列Q中。

3. while(Q不为空)

    {

    取出队列中的第一个点,删去这个点的相邻边。并将这个点删除。

    如果发现删除这个点相邻边后,有点的出度为0,则将这个点压入队列尾。

    }

4.若没有点剩余,则全部能去,反之不行。

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <queue>
 6 
 7 using namespace std;
 8 
 9 const int MAX = 100010;
10 
11 vector<int> edge[MAX];
12 queue<int> Q;
13 int out[MAX];
14 
15 void init(int n){
16     for(int i = 1 ; i <= n ; i++){
17         edge[i].clear();
18     }
19     return;
20 }
21 
22 int main(){
23     
24     int t;
25     scanf("%d",&t);
26     
27     while(t--){
28         int N;
29         scanf("%d",&N);
30         int all = N;
31         while(!Q.empty()) Q.pop();
32         init(N);
33         //////////////////////
34         for(int i = 1 ; i <= N ; i++){
35             int k;
36             scanf("%d",&k);
37             out[i] = k;
38             if(!k) Q.push(i);
39             for(int j = 0 ; j < k ; j++){
40                 int temp;
41                 scanf("%d",&temp);
42                 edge[temp].push_back(i);
43             }
44         }
45         //////////////////////
46         
47         while(!Q.empty()){
48             int now  = Q.front();
49             Q.pop();
50             all--;
51             ///////
52             int size = edge[now].size();
53             for(int i = 0;  i < size ; i++){
54                 int op = edge[now][i];
55                 out[op]--;
56                 if(out[op] == 0) Q.push(op);
57             }
58         }
59         
60         ///////////
61         if(all) printf("No\n");
62         else printf("Yes\n");
63         
64     }
65     
66     return 0;
67 }
View Code

 

 

Problem I :  Alex’s Foolish Function

时间限制: 8 Sec  内存限制: 128 MB

题目描述:

Alex has an array F which size is n, initially each element’s value is zero. Now he wants to operate the array, he has 4 different functions:

1) Function A(l, r):

Add the elements between l to r (inclusive) where the ith add i - l + 1, for instance, if l is 4,

r is 6 and the elements between 4 to 6 is 3 4 10, after this operation, these elements will become 4 6 13.

2) Function B(l, r):

Add the elements between l to r (inclusive) where the ith add r - i + 1, for instance, if l is 4,

r is 6 and the elements between 4 to 6 is 3 4 10, after this operation, these elements will become 6 6 11.

3) Function C(l, r, x):

Set all the elements(between l to r) to x, for instance, if l is 4, r is 6 and the elements

between 4 to 6 is 3 4 10, and x = 2, after this operation, these elements will become 2 2 2.

4) Function S(l, r):

Output Fl + Fl+1 + Fl+2 + ...+ Fr. 

 

输入:

Input start with an integer T(1 <= T <= 5), denoting the number of test case.

For each test case, first line contains n, m (1 <= n <= 200000, 1 <= m <= 100000), denoting the array’size and the number of operations.

Next m lines, each line contains an operation, formatting as

A l r

B l r

C l r x

S l r 

 

输出:

For each S Function operations, output the sum. 

 

样例输入:

1

5 4

A 1 3

B 2 5

C 1 1 2

S 1 5

样例输出:

17

 

题解:

 

按照提议模拟操作,但是要套数据结构,线段树。

 

代码:

技术分享
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 const double pi = acos(-1.0);
  5 const int inf = 0x3f3f3f3f;
  6 const double eps = 1e-15;
  7 typedef long long LL;
  8 typedef unsigned long long ULL;
  9 typedef pair <int, int> PLL;
 10 const LL INF = (1LL << 60);
 11 
 12 const int N = 250010;
 13 struct SegTree {
 14     int l, r;
 15     LL add1, add2, add3; //add1 -> 覆盖, add2->加某个值, add3->加减下标
 16     LL sum;
 17 }tree[N << 2];
 18 
 19 void pushup(int p) {
 20     tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
 21 }
 22 
 23 void pushdown(int p) {
 24     if (tree[p].add1 != -inf) {
 25         tree[p << 1].add2 = tree[p << 1].add3 = tree[p << 1 | 1].add2 = tree[p << 1 | 1].add3 = 0;
 26         tree[p << 1].add1 = tree[p << 1 | 1].add1 = tree[p].add1;
 27         tree[p << 1].sum = tree[p].add1 * (tree[p << 1].r - tree[p << 1].l + 1);
 28         tree[p << 1 | 1].sum = tree[p].add1 * (tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1);
 29         tree[p].add1 = -inf;
 30     }
 31     if (tree[p].add2) {
 32         tree[p << 1].add2 += tree[p].add2;
 33         tree[p << 1 | 1].add2 += tree[p].add2;
 34         tree[p << 1].sum += tree[p].add2 * (tree[p << 1].r - tree[p << 1].l + 1);
 35         tree[p << 1 | 1].sum += tree[p].add2 * (tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1);
 36         tree[p].add2 = 0;
 37     }
 38     if (tree[p].add3) {
 39         tree[p << 1].add3 += tree[p].add3;
 40         tree[p << 1 | 1].add3 += tree[p].add3;
 41         tree[p << 1].sum += tree[p].add3 * (LL)(tree[p << 1].r - tree[p << 1].l + 1) * (tree[p << 1].l + tree[p << 1].r) / 2;
 42         tree[p << 1 | 1].sum += tree[p].add3 * (LL)(tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1) * (tree[p << 1 | 1].l + tree[p << 1 | 1].r) / 2;
 43         tree[p].add3 = 0;
 44     }
 45 }
 46 
 47 void build(int p, int l, int r) {
 48     tree[p].l = l;
 49     tree[p].r = r;
 50     tree[p].sum = tree[p].add2 = tree[p].add3 = 0;
 51     tree[p].add1 = -inf;
 52     if (l == r) {
 53         return;
 54     }
 55     int mid = (l + r) >> 1;
 56     build(p << 1, l, mid);
 57     build(p << 1 | 1, mid + 1, r);
 58 }
 59 
 60 void update(int p, int l, int r, int id, int val) {
 61     if (l <= tree[p].l && tree[p].r <= r) {
 62         if (id == 1) {
 63             tree[p].add1 = (LL)val;
 64             tree[p].add2 = tree[p].add3 = 0;
 65             tree[p].sum = (LL)val * (tree[p].r - tree[p].l + 1);
 66         }
 67         else if (id == 2) {
 68             tree[p].add2 += (LL)val;
 69             tree[p].sum += (LL)val * (tree[p].r - tree[p].l + 1);
 70         }
 71         else {
 72             tree[p].add3 += (LL)val;
 73             tree[p].sum += (LL)val * (LL)(tree[p].r - tree[p].l + 1) * (LL)(tree[p].l + tree[p].r) / 2;
 74         }
 75         return;
 76     }
 77     pushdown(p);
 78     int mid = (tree[p].l + tree[p].r) >> 1;
 79     if (r <= mid) {
 80         update(p << 1, l, r, id, val);
 81     }
 82     else if (l > mid) {
 83         update(p << 1 | 1, l, r, id, val);
 84     }
 85     else {
 86         update(p << 1, l, mid, id, val);
 87         update(p << 1 | 1, mid + 1, r, id, val);
 88     }
 89     pushup(p);
 90     //printf("区间[%d, %d], sum = %lld\n", tree[p].l, tree[p].r, tree[p].sum);
 91 }
 92 
 93 LL query(int p, int l, int r) {
 94     if (l <= tree[p].l && tree[p].r <= r) {
 95         return tree[p].sum;
 96     }
 97     pushdown(p);
 98     int mid = (tree[p].l + tree[p].r) >> 1;
 99     if (r <= mid) {
100         return query(p << 1, l, r);
101     }
102     else if (l > mid) {
103         return query(p << 1 | 1, l, r);
104     }
105     else {
106         return query(p << 1, l, mid) + query(p << 1 | 1, mid + 1, r);
107     }
108 }
109 
110 int main() {
111     int t;
112     scanf("%d", &t);
113     while (t--) {
114         int n, m, l, r, val;
115         char str[3];
116         scanf("%d%d", &n, &m);
117         build(1, 1, n);
118         while (m--) {
119             scanf("%s", str);
120             if (str[0] == S) {
121                 scanf("%d%d", &l, &r);
122                 printf("%lld\n", query(1, l, r));
123             }
124             else if (str[0] == A) {
125                 scanf("%d%d", &l, &r);
126                 update(1, l, r, 2, 1 - l);
127                 update(1, l, r, 3, 1);
128             }
129             else if (str[0] == B) {
130                 scanf("%d%d", &l, &r);
131                 update(1, l, r, 2, r + 1);
132                 update(1, l, r, 3, -1);
133             }
134             else {
135                 scanf("%d%d%d", &l, &r, &val);
136                 update(1, l, r, 1, val);
137             }
138         }
139     }
140     return 0;
141 }
View Code

 

 

Problem J : 对数问题

时间限制: 1 Sec  内存限制: 64 MB

 

题目描述:

Alex有一个问题,给你一个数组,然后给你一个数k,问你数组中和为k的数对有多少对(各个对中下标不同就算一对)。

 

输入:

有t(t <= 10)组数,每组给你数n(n <= 100)和k(k <= 10000),表示数组的大小,然后下面给你n个数ai(1 <= ai <= 100)表示数组的元素大小。

 

输出:

输出和为k的对数有多少对,没有的话为0。

 

样例输入:

1

4 3

1 2 1 2

样例输出:

4

 

题解:

 

和对数一点关系都没有,是“数对问题”比较贴切吧。

还是很水的,全部试一遍就好了,两个for,有点像A题,只是这题要你数出几个,不要数重复就好。

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <string>
 7 using namespace std;
 8  
 9 long long  save[10010];
10 int main(){
11     int t;
12     cin >> t;
13     while(t--){
14         int n;
15         int K;
16         cin >> n;
17         cin >> K;
18         for(int i = 1; i <= n ; i++){
19             cin >> save[i];
20         }
21         for(int i = 1 ; i <= n; i++){
22             sum[i] = save[i] + sum[i - 1];
23         }
24         int ans = 0;
25         for(int i = 1 ; i <= n; i++){
26             for(int j = i + 1 ; j <= n ; j++){
27                 if(save[i] + save[j] == K) ans++;
28             }
29         }
30         ///
31         cout << ans << endl;
32     }
33     return 0;
34 }
View Code

 

 

Problem K : Page Fault

时间限制: 1 Sec  内存限制: 64 MB

题目描述:

要说起操作系统存储器管理,少不了要谈下分页存储管理,它把进程的虚拟地址空间和实际

的主存地址空间划分为同样?小的页(1KB,2KB或者4KB),然后提供一种从虚拟地址到实际物理地址的翻译机制。另外,虚拟地址空间还把一些表?完整信息的?划分为一个段,且每个段都有?个权限要求。

如果一个虚拟地址?法找到对应的实际物理地址,CPU就会引发一个缺?中断,但是在这之 前,CPU必须知道这个地址是否合法,简单来说,CPU会把这个地址和虚拟地址空间的各个段?较,如果地址没有落在这些段?,或者虽然在一个段中,但是权限不够,就会产?一个Segment Fault 异常;否则说明这是一个合法地址,可以进?页面调度。 

 

输入:

第?行有?个整数T,代表数据组数(T <= 1000)。 每组数据包含一个整数n(1 <= n <= 100),代表段的数目。 接下来n行,包含三个整数 start, end, prot,start是开始地址, end是结束地址,prot是对应权限,保证段与段之间不相交 (即不会出现诸如[3,5], [5,7]之类的情况)。 最后?行包含一个整数address,表?示需要验证的地址。

(0 <= start, end, address <= 231 - 1, 0 <= prot <= 1) 假设我们的程序对prot为1的段没有权限,所以无法访问这些段。

 

输出:

对于每组数据,如果产?生了段错误,输出Segment Fault,否则输出Missing Page Interrupt。 

 

样例输入:

3

3

0 3 1

4 5 0

6 8 1

7

1

0 3 1

2

0 0 0

1 3 0

2

样例输出:

Segment Fault

Segment Fault

Missing Page Interrupt

 

 

题解:

 

用结构体纪录每一个给你的区间的上下段,和记录这个区间的权限,设置成数组,读入所有的段,然后for一遍就可以了,水题。

特别注意一下,假如给你的段最大到达 比如是 8 , 他给你地址是 10 的时候,输出也是 fualt.

我用了long long,貌似是不需要的,用int存就可以了。

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <string>
 7 using namespace std;
 8  
 9 pair<long long , long long> save[100010];
10 bool pro[10100];
11  
12 int main(){
13     int t;
14     cin >> t;
15     while(t--){
16         int n;
17         scanf("%d",&n);
18         for(int i = 0; i < n ; i++){
19             long long temp1 , temp2 , p;
20             cin >> temp1 >> temp2 >> p;
21             save[i] = make_pair(temp1,temp2);
22             if(p == 1) pro[i] = 1;
23             else pro[i] = 0;
24         } 
25         long long add;
26         cin >> add;
27         bool ok = 0;
28         for(int i = 0; i < n ; i++){
29             long long begin = save[i].first;
30             long long end = save[i].second;
31             ////
32             if(add >= begin && add <= save[i].second){
33                 if(pro[i] == 1) ok = 0;
34                 else ok = 1;
35                 break;
36             }
37         }
38         ///
39         if(!ok) cout << "Segment Fault" << endl;
40         else cout << "Missing Page Interrupt" << endl;
41     }
42     return 0;
43 }
View Code

 

 

Problem L : VectorMultiply

时间限制: 1 Sec  内存限制: 64 MB

题目描述:

 

There are two vector A(x1, x2, x3, ..., xn) and B(y1, y2, ..., yn), and the dot product(点积) is x1*y1 + x2*y2 + ... + xn*yn.

You can swap the order of any dimension, for example, A = {1, 2, 3}, then you can make A to {1, 3, 2} or {2, 1, 3} and so on.

Now you need to calculate the maximum value of dot product.

 

输入:

 

Input starts with an integer T (T <= 20)denoting the test case.

For each test case, first line contains n(n <= 10000)

then two lines follow, each line contains n integers(1 <= xi, yi <= 100000).

 

输出:

For each test case, print the maximum value of dot product.

 

样例输入:

1

4

1 3 2 10

2 3 4 1

样例输出:

54

 

题解: 

这两个向量里面的数字都是正数,那么就很简单了,大的乘大的,小的乘小的就好。用sort排序啊,自己写个冒泡的话,实在效率太低了.......

 

代码:

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stack>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <string>
 7 using namespace std;
 8  
 9 long long  save1[10010];
10 long long  save2[10010];
11 int main(){
12     int t;
13     cin >> t;
14     while(t--){
15         long long ans = 0;
16         int n;
17         cin >> n;
18         for(int i = 0 ; i < n ; i++){
19             cin >> save1[i];
20         }
21         for(int i = 0 ; i < n ; i++){
22             cin >> save2[i];
23         }
24         sort(save1,save1+n);
25         sort(save2,save2+n);
26         for(int i = 0 ; i < n ; i++){
27             ans += (save1[i] * save2[i]);
28         }   
29         cout << ans << endl;
30     }
31     return 0;
32 }
View Code

 

 

 

Problem M : Hot Hot Up

时间限制: 1 Sec  内存限制: 64 MB

 

题目描述:

欢迎参加本次比赛,请输出谚语: “A young idler, an old beggar”。 

 

 

输入:

本题没有输?。 

 

输出:

输出”A young idler, an old beggar”(不含引号)。 

 

样例输出:

A young idler, an old beggar

 

题解:

 

作为本场比赛最难的一道题,我真不知道这题题解怎么写。

 

代码:

技术分享
1 #include <iostream>
2 #include <cstdio>
3 using namespace std;
4 int main(){
5     printf("A young idler, an old beggar\n");
6     return 0;
7 }
8  
View Code

 

2016 年宁波工程学院第七届ACM校赛题解报告

标签:

原文地址:http://www.cnblogs.com/ticsmtc/p/5478434.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!