cumt2017春季——周练

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cumt2017春季——周练相关的知识,希望对你有一定的参考价值。

A.Bear and Big Brother

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int x, y;
 6     scanf("%d%d", &x, &y);
 7 
 8     int ans = 0;
 9     while(x <= y)
10     {
11         x *= 3;
12         y *= 2;
13         ans++;
14     }
15     printf("%d\n", ans);
16     return 0;
17 }

 

B.The Monster(暴力)

题意:

  给定整数a,b,c,d(1<=a,b,c,d<=100),求是否有y满足  y=a*x1+b=c*x2+d。x1,x2为正整数。
思路:
  我们考虑成两条直线在坐标系上,然后你想极端情况,两者相交使得y最大,是不是a=c=100的时候,在无穷远处相交(平行嘛),那么c小一点点y=99x+100,y=100x+0。所以可以发现y的范围肯定不会超过10000。所以暴力出10000的范围内的数据,匹配一下有无答案就行了。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int a, b, c, d;
 5 
 6 int solve()
 7 {
 8     map<int, int>ma;
 9     int y = b;
10     while(y <= 10000)
11     {
12         ma[y]++;
13         y += a;
14     }
15 
16     y = d;
17     while(y <= 10000)
18     {
19         if(ma[y] != 0)  return y;
20         y += c;
21     }
22     return -1;
23 }
24 
25 int main()
26 {
27     scanf("%d%d%d%d", &a, &b, &c, &d);
28     printf("%d\n", solve());
29     return 0;
30 }

 

C.Bear and Friendship Condition(并查集)

题意:

  如果1认识2,2认识3,必须要求有:1认识3.如果满足上述条件,输出YES,否则输出NO. 

思路:

  拿并查集维护朋友关系,维护并查集的同时维护一个cnt数组,cnt[root]代表以root为根节点的并查集的大小是cnt[root]个。那么验证是否整张图满足条件的方法就是,对于任意一个点i,它的度数应该是cnt[ pa[i] ] - 1。即,它所在的朋友圈有k人,则它应该有k-1条边。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 150000 + 5;
 4 int pa[maxn];
 5 set<int>G[maxn];
 6 int cnt[maxn];
 7 void init(int n)
 8 {
 9     for(int i = 0; i <= n; i++) pa[i] = i, cnt[i] = 1;
10 }
11 int uf_find(int x){return x == pa[x] ? x : (pa[x] = uf_find(pa[x]));}
12 
13 void uf_join(int x, int y)
14 {
15     int fx = uf_find(x), fy = uf_find(y);
16     if(fx != fy)
17         pa[fx] = fy, cnt[fy] += cnt[fx];
18 }
19 
20 bool judge(int n)
21 {
22     for(int i = 1; i <= n; i++)
23     {
24         int fi = uf_find(i);
25         if(i != fi && G[i].size() + 1 != cnt[fi])
26         {
27             return false;
28         }
29     }
30     return true;
31 }
32 int main()
33 {
34     init(150000);
35     int n, m;
36     scanf("%d%d", &n, &m);
37     for(int i = 0; i < m; i++)
38     {
39         int x, y;
40         scanf("%d%d", &x, &y);
41         G[x].insert(y);
42         G[y].insert(x);
43         uf_join(x, y);
44     }
45     if(judge(n)) puts("YES");
46     else puts("NO");
47 
48     return 0;
49 }

 

 

F.UVA 10970(思维)

题意:

  给你一块M*N的巧克力,问把它切成最小单元需要最少切几刀,分开的就不能一起切了。

思路:

  每次下刀,只能多增加一块,一共需要切成m*n块,所以显然答案。

 1 #include <stdio.h>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int mod = 1e9 + 7;
 5 const int maxn = 1000000 + 5;
 6 const int INF = 0x3f3f3f3f;
 7 typedef long long LL;
 8 typedef unsigned long long ull;
 9 
10 
11 int main()
12 {
13     int n, m;
14     while(cin >> n >> m)    cout << n * m - 1 << endl;
15     return 0;
16 }

 

G.UVA - 10340(经典问题)

题意:

  从字符串s中删除一些字符,能否得到字符串t。

 1 #include <stdio.h>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int mod = 1e9 + 7;
 5 const int maxn = 1000000 + 5;
 6 const int INF = 0x3f3f3f3f;
 7 typedef long long LL;
 8 typedef unsigned long long ull;
 9 
10 bool solve(string &s, string &t)
11 {//从t中删除  能否得到s
12     int lens = s.length(), lent = t.length();
13     int cnt = 0;
14     for(int i = 0; i < lent; i++)
15     {
16         if(s[cnt] == t[i])  cnt++;
17     }
18     return cnt == lens;
19 }
20 
21 int main()
22 {
23     string a, b;
24     while(cin >> a >> b)
25     {
26         printf("%s\n", solve(a, b) ? "Yes" : "No");
27     }
28     return 0;
29 }

 

H.UVA 10382(经典贪心)

题意:

  有一块草坪,长为l,宽为w,在它的水平中心线上有n个位置可以安装喷水装置,各个位置上的喷水装置的覆盖范围为以它们自己的半径ri为圆。求出最少需要的喷水装置个数。

思路:

  每个圆,和草坪边界交点,化成一个线段,然后问题就变成,最少需要几个小区间覆盖整个大区间。

 1 #include <stdio.h>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int mod = 1e9 + 7;
 5 const int maxn = 10000 + 5;
 6 const int INF = 0x3f3f3f3f;
 7 const double eps = 1e-8;
 8 typedef pair<int, int>pii;
 9 typedef pair<double, double>pdd;
10 typedef long long LL;
11 typedef unsigned long long ull;
12 
13 int n, l;
14 double w;
15 pdd a[maxn];
16 
17 bool cmp(pii x, pii y)
18 {
19     if(x.first != y.first)  return x.first < y.first;
20     return x.second < y.second;
21 }
22 
23 int solve()
24 {
25     double last, temp;
26     if(a[0].first - 0 > eps)    return -1;
27 
28     int ans = 0;
29     double cur = 0, far = 0;
30     for(int i = 0; i < n; i++)
31     {
32         if(cur >= l)    return ans;
33         if(a[i].first <= cur)
34         {
35             far = max(far, a[i].second);
36         }
37         else if(a[i].first > cur)
38         {
39             ans++;
40             cur = far;
41             if(a[i].first <= cur)
42             {
43                 far = max(far, a[i].second);
44             }
45             else
46             {
47                 return -1;
48             }
49         }
50     }
51     if(cur < l && far >= l) return ans + 1;
52     if(far < l) return -1;
53     return ans;
54 }
55 
56 int main()
57 {
58 
59     while(~scanf("%d%d%lf", &n, &l, &w))
60     {
61         for(int i = 0; i < n; i++)
62         {
63             double pos, r;
64             scanf("%lf%lf", &pos, &r);
65             double d = sqrt(r * r - w / 2 * w / 2);
66             a[i].first = pos - d, a[i].second = pos + d;
67         }
68         sort(a, a + n, cmp);
69 
70         cout << solve() << endl;
71 
72 
73     }
74     return 0;
75 }

 

I.UVA 10905

题意:

  给n个数字,将它们重新排序得到一个最大的数字,比如给出123 456 789 拼为 789456123 最大。

思路:

  两两贪心!

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int mod = 1e9 + 7;
 4 const int maxn = 50 + 5;
 5 const int INF = 0x3f3f3f3f;
 6 typedef long long LL;
 7 typedef unsigned long long ull;
 8 
 9 
10 string num[maxn];
11 bool cmp(string &a, string &b)
12 {
13     return a + b > b + a;
14 }
15 int main()
16 {
17     int n;
18     while(~scanf("%d", &n))
19     {
20         if(n == 0)  break;
21         for(int i = 0; i < n; i++)
22         {
23             cin >> num[i];
24         }
25         sort(num, num + n, cmp);
26         for(int i = 0; i < n; i++)
27         {
28             cout << num[i];
29         }
30         puts("");
31     }
32 
33     return 0;
34 }

 

J.Bear and Different Names(构造)

题意:

  连续k个人不可有相同的名字

思路:

  先这样考虑,把1-n的位置置为1,2,3,...,n。

  那么显然,如果是YES,则一直满足条件,保持不变就好了。如果当前位置是i,指令为NO,那么我们要做一些什么更改呢,只要需要把[i,i + k -1]这k个数中的最后一个数字,a[i + k - 1] = a[i]。满足了当前区间是NO,且自i+1到n仍保持原来的属性,一直为YES。就这样就能构造出一个满足条件的序列了。

  然后暴力搞个随机,打个名字的表就行了。这个表就相当于1,2,3,4,...,n。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 string name[205] = {"x", "Aa", "Bb" , "Cc", "Dd", "Ee" , "Ff" ,"Gg" , "Hh" , "Aaahglnt", "Aabgrtea", "Aafonkti", "Aawqffot", "Abrdbgnk", "Abyjfndo", "Accpphya", "Acgomdfb", "Acluatrp", "Acqsuwoo", "Acycmioj", "Adbbnytt", "Adezrgnv", "Adpxbmca", "Adrwxynk", "Adsnvthx", "Aduyfgmr", "Adxqjpat", "Aelugsgs", "Aewdbttu", "Afedjbpj", "Afkxdttk", "Afnvzafm", "Afwuokpd", "Afzdheck", "Agbifunf", "Ageroseh", "Aglaxgkb", "Agtugeun", "Ahciylyk", "Ahmotmkm", "Ahvmlmgd", "Aibzmjut", "Aietskor", "Aijobbfm", "Aiwqoywv", "Aizqcqyk", "Ajdcuoru", "Ajhcougy", "Ajqgndza", "Akcwqtid", "Akqqmuds", "Albduoty", "Alouzmpd", "Alyfdfht", "Amasunlb", "Amfxvkla", "Amqdqqev", "Amzwqtac", "Annzdvny", "Anwaoawm", "Aoovgcnb", "Apenhcdf", "Apksqkac", "Apycnnpq", "Aqizeqkf", "Aqjdpzvz", "Aqjjjsti", "Aqzpxguv", "Arfpgnot", "Ariqfihl", "Arjiqibc", "Arnqekvn", "Arqbkcaz", "Arrehjpl", "Arrlxuye", "Asgvgjfs", "Asiscmhj", "Asrmwabq", "Asvltjfr", "Asygsfgd", "Atigqiad", "Atnjqfhz", "Atpnekrx", "Atssgtgi", "Attpyxgu", "Auistszb", "Aumsoyfg", "Auvcsdfw", "Avckiwod", "Avdzmoya", "Avghyxfs", "Avpxrnmj", "Avuluuib", "Avydzsuu", "Avzpiaan", "Awbsnegp", "Awfwltto", "Awkrjqfk", "Awyqizql", "Awzvzzow", "Axkjllvg", "Axkoiemu", "Axqdgzee", "Aydinhlv", "Aythxbyg", "Azilfijf", "Azjgihgu", "Aztmjzrk", "Azzbiwet"};
 4 int main()
 5 {
 6     int n, k;
 7     scanf("%d%d", &n, &k);
 8 
 9     for(int i = 1; i <= n - k + 1; i++)
10     {
11         char s[20];
12         scanf("%s", s);
13         if(s[0] == N)//NO
14         {
15             name[i + k - 1] = name[i];
16         }
17     }
18     for(int i = 1; i <= n; i++)
19     {
20         cout << name[i] <<(i == n ? \n :  );
21     }
22     return 0;
23 }

 

以上是关于cumt2017春季——周练的主要内容,如果未能解决你的问题,请参考以下文章

cumt训练赛题解

周练1

JOI2017 春季合宿:Railway Trip

周练4

周练7

周练5