20190402——第一场UPC团队训练

A

题意:将一组数字分成两组,要求一组的任意数字都比另一组的任意数字大。

思路:简单sort后比较最中间的两个数字的大小即可。

 1 #include <bits/stdc++.h>
 2 using namespace std ;
 3  
 4 int a[200005];
 5 int main()
 6 {
 7     int n,T;
 8     cin >> T;
 9     while(T --){
10         cin >> n;n += n;
11         for(int i = 1;i <= n;i ++){
12             cin >> a[i];
13         }
14         for(int i = 1;i <= n;i ++){
15             int t;cin >> t;
16             a[i] += t;
17         }
18         sort(a + 1,a + n + 1);
19         if(a[n / 2] < a[(n / 2) + 1]){
20             cout << "Cheat" << endl;
21         }
22         else{
23             cout << "Fail" << endl;
24         }
25     }
26 }
A

B

题意:在一组偶数个数的数字中,只有两个数字出现了一次,按照从大到小输出这两个数。

思路:简单模拟即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 int x[1000000+5];
 5 int main()
 6 {
 7     int n;
 8     cin>>n;
 9     for(int ii = 1;ii<=n;ii++)
10     {
11         int s;
12         cin>>s;
13         for(int i = 1;i<=s;i++)
14         {
15             scanf("%d",x+i);
16         }
17         sort(x+1,x+s+1);
18         int j = s;
19         int flag = 0;
20         while(j>=1)
21         {
22             if(x[j] == x[j - 1])
23             {
24                 j = j-2;
25             }
26             else
27             {
28                 cout<<x[j];
29                 if(flag == 0)
30                 {
31                     cout<<" ";
32                     flag = 1;
33                 }
34                 else
35                 {
36                     cout<<endl;
37                 }
38                 j--;
39             }
40         }
41     }
42 }
B

C

题意:给两个杯子的容量和目标体积,有给出三种操作:

   把某个杯子倒满;

   把某个被子倒空;

   把某个杯子的水倒到另一个杯子,知道这个杯子空或者那个杯子满。

   求出某个杯子变成目标容量的最小操作数。

思路:简单BFS,搜索6种情况。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 int n,m,k;
 5 int F;
 6 void bfs(){
 7     map<pair<int,int>,int > M;
 8     queue<pair<int,int> > Q;
 9     Q.push(make_pair(0,0));
10     M[make_pair(0,0)] = 1;
11     while(Q.size()){
12         pair<int,int> P = Q.front();
13         Q.pop();
14         if(P.first == k || P.second == k){
15             F = 0;
16             cout << M[P] - 1 << endl;
17             break;
18         }
19         if(P.first != n){ /// full n
20             pair<int,int> t = make_pair(n,P.second);
21             if(M[t] == 0){
22                 Q.push(t);
23                 M[t] = M[P] + 1;
24             }
25         }
26         if(P.second != m){ /// full m
27             pair<int,int> t = make_pair(P.first,m);
28             if(M[t] == 0){
29                 Q.push(t);
30                 M[t] = M[P] + 1;
31             }
32         }
33         if(P.first != 0){ /// drop n
34             pair<int,int> t = make_pair(0,P.second);
35             if(M[t] == 0){
36                 Q.push(t);
37                 M[t] = M[P] + 1;
38             }
39         }
40         if(P.second != 0){ /// drop m
41             pair<int,int> t = make_pair(P.first,0);
42             if(M[t] == 0){
43                 Q.push(t);
44                 M[t] = M[P] + 1;
45             }
46         }
47         if(P.second != m && P.first != 0){ /// n to m
48             pair<int,int> t;
49             if(P.first + P.second <= m){
50                 t.first = 0;
51                 t.second = P.first + P.second;
52             }
53             else{
54                 t.first = P.first + P.second - m;
55                 t.second = m;
56             }
57             if(M[t] == 0){
58                 Q.push(t);
59                 M[t] = M[P] + 1;
60             }
61         }
62         if(P.second != 0 && P.first != n){ /// m to n
63             pair<int,int> t;
64             if(P.first + P.second <= n){
65                 t.first = P.first + P.second;
66                 t.second = 0;
67             }
68             else{
69                 t.first = n;
70                 t.second = P.first + P.second - n;
71             }
72             if(M[t] == 0){
73                 Q.push(t);
74                 M[t] = M[P] + 1;
75             }
76         }
77     }
78 }
79  
80 int main()
81 {
82     while(cin >> n >> m >> k){
83         F = 1;
84         bfs();
85         if(F){cout << "impossible" << endl;}
86     }
87 }
C

D

题意:对于给定长度n,写出一组数字 1,2,3......2 * n 。

   每次操作为:对1-2n的序列进行如下移动:每次将前n个数字取出,按顺序依次插入到位于n+1,n+2...2n的数字后面。

   求多少次移动后会变回原来的序列。

思路:只需要对任意一个数字,追踪他的位置即可找到规律:i = (i * 2) % (2 * n + 1)。(破题卡我cin和cout)

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

E

题意:给两个数字,每次可以对任何一个数字进行除2或者除3,求最少多少次能将这两个数字变成相等。

思路:两个数字先除Gcd,然后分解因数即可。

 1 #include <bits/stdc++.h>
 2 using namespace std ;
 3  
 4 int main()
 5 {
 6     int n,m;
 7     while(cin >> n >> m){
 8         int G = __gcd(n,m);
 9         n /= G;m /= G;
10         int cnt = 0 ;
11         while(n % 2 == 0){
12             n /= 2;
13             cnt ++;
14         }
15         while(n % 3 == 0){
16             n /= 3;
17             cnt ++;
18         }
19         while(m % 2 == 0){
20             m /= 2;
21             cnt ++;
22         }
23         while(m % 3 == 0){
24             m /= 3;
25             cnt ++;
26         }
27         if(n != m){cout << "-1" << endl;}
28         else{cout << cnt << endl;}
29     }
30 }
E

G

题意:给若干个区间,对于每次输入后,输出当前所有区间的并。出现多个区间则用逗号隔开。

思路:暴力模拟。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 int n,m,k;
 5  
 6 bitset<1005> isok ;
 7  
 8 int main()
 9 {
10     int n ,k;
11     scanf("%d%d",&n,&k) ;
12     isok=0;
13     for(int i(1);i<=k;++i) {
14         int l,r ;
15         scanf("%d%d",&l,&r) ;
16         for(int j(l);j<=r;++j) {
17             isok[j] = 1 ;
18         }
19         int s(-1) ;
20         vector<pair<int,int> > v ;
21         for(int i(1);i<=n+1;++i) {
22             if(isok[i] == 1&&s == -1) {
23                     ////cout << i <<endl;
24                 s = i ;
25             }
26             if(isok[i] != 1&&s != -1) {
27                 v.push_back(make_pair(s,i-1)) ;
28                 s = -1 ;
29             }
30         }
31         /// cout<<"Size == "<<v.size()<<endl ;
32         for(int i(0);i<v.size();++i) {
33             cout<<"["<<v[i].first<<","<<v[i].second<<"]" ;
34             if(i == v.size()-1) {
35                 cout<<endl;
36             } else {
37                 cout<<",";
38             }
39         }
40     }
41 }
G

I

题意:有一堆重物,给一串数字,代表每个重物的重量是pow(2,ai)。每次能拿出总共重量是2的幂次的重物。求解最少搬运次数。

思路:桶排一下,然后往后扫即可。(这题WA了两次,实在该打)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 int n,m,k;
 5 int F,vis[2000003];
 6 //priority_queue<int,vector<int> ,greater<int> > Q;
 7  
 8 int main()
 9 {
10     while(cin >> n){
11             memset(vis,0,sizeof(vis));
12         for(int i = 0;i < n;i ++){
13             cin >> m;
14             vis[m] ++;
15         }
16         for(int i = 0;i <= 1500000;i ++){
17             vis[i + 1] += vis[i] / 2;
18             vis[i] = vis[i] % 2;
19         }
20         int cnt = 0;
21         for(int i = 0;i <= 1500000;i ++){
22             if(vis[i]){cnt ++;}
23  
24         }
25         cout << cnt << endl;
26  
27     }
28 }
I

J

题意:给一串数字,规定某个区间的价值是该区间内所有数字的和再乘上这个区间内的最小数字。求解最大的区间价值和区间。

思路:对于任意数字,分别找到左右第一个比他小的数字,那么他对应的最优区间就是这段。(神仙队友分块分一切过了,别的队伍有花式二分的)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 int n,m,k;
 5 const int MAXN (1000005) ;
 6 int arr[MAXN] ;
 7 int64_t sum[MAXN],ans ;
 8 int l,r ;
 9 int pos[MAXN],L[MAXN],R[MAXN],bCnt ;
10 pair<int,int> a[MAXN];
11 int mins[MAXN] ;
12  
13 void Init(int n)
14 {
15     int bSize = (int)sqrt(n) ;
16     bCnt = n/bSize ;
17     R[0] = 0 ;
18     for(int i(1);i<=bCnt;++i) {
19         L[i] = R[i-1] + 1 ;R[i] = i*bSize ;
20         sort(a+L[i],a+R[i]+1) ;
21         mins[i] = a[L[i]].first ;
22         for(int j(L[i]);j<=R[i];++j) {
23           ///  printf("	<%d,%d>
",a[j].first,a[j].second) ;
24             pos[j] = i ;
25         }
26         /// cout<<endl;
27         ///printf("	mins[%d] == %d
",i,mins[i]) ;
28  
29     }
30     if(R[bCnt]!=n) {
31         L[++bCnt] = R[bCnt-1] + 1;
32         R[bCnt] = n ;
33         sort(a+L[bCnt],a+R[bCnt]+1) ;
34         mins[bCnt] = a[L[bCnt]].first ;
35     }
36     for(int i(L[bCnt]);i<=R[bCnt];++i) pos[i] = bCnt ;
37 }
38  
39 void solve()
40 {
41     l = r = -1 ;
42     ans = -999 ;
43     int LL,RR ;
44     for(int i(1);i<=n;++i) {
45         LL = 1,RR = n ;
46         bool isLok = false ;
47         for(int j(pos[i]);j>=1;--j) {
48             ///printf("mins[%d] == %d
",j,mins[j]) ;
49             if(mins[j]<arr[i]) {
50                 int p(L[j]),q(R[j]) ;
51                 for(int k(p);k<=q;++k) {
52                     if(a[k].first<arr[i]&&a[k].second<=i) {
53                         if(LL<=a[k].second) {
54                             LL = a[k].second + 1 ;
55                         }
56                     }
57                 }
58             }
59             if(LL!=1) break ;
60         }
61         for(int j(pos[i]);j<=bCnt;++j) {
62             if(mins[j]<arr[i]) {
63                 int p(L[j]),q(R[j]) ;
64                 for(int k(p);k<=q;++k) {
65                     if(a[k].first<arr[i]&&a[k].second>=i) {
66                         if(RR>=a[k].second) {
67                             RR = a[k].second - 1 ;
68                         }
69                     }
70                 }
71             }
72             if(RR!=n) break ;
73         }
74         ///printf("	%d: L == %d,R == %d
",i,LL,RR) ;
75         if(1LL*arr[i]*(sum[RR]-sum[LL-1])>ans) {
76             ans = 1LL*arr[i]*(sum[RR]-sum[LL-1]) ;
77             l = LL,r = RR ;
78         }
79     }
80 }
81  
82 int main()
83 {
84     while(~scanf("%d",&n))
85     {
86         sum[0] = 0 ;
87         for(int i(1);i<=n;++i) {
88             scanf("%d",arr+i) ;
89             a[i] = make_pair(arr[i],i) ;
90             sum[i] = sum[i-1] + arr[i] ;
91         }
92         Init(n) ;
93         solve() ;
94         printf("%lld
%d %d
",ans,l,r) ;
95     }
96 }
J

K

题意:求字符串的最小循环节长度。

思路:套板子。(队友实力套了个最小循环节个数的板子,无脑WA一发。。。)

 1 #include <bits/stdc++.h>
 2  
 3 using namespace std;
 4 const int MAXN(1000005) ;
 5 int Next[MAXN] ;
 6 char s1[MAXN] ;
 7 int len1 ;
 8 inline void get_next()
 9 {
10     int t1=0,t2;
11     Next[0] = t2 = -1 ;
12     while(t1<len1) {
13         if(t2 == -1||s1[t1] == s1[t2]) {
14             Next[++t1] = ++t2 ;
15         } else {
16             t2 = Next[t2] ;
17         }
18     }
19 }
20  
21 int main()
22 {
23     while(~scanf("%s",s1)) {
24         len1 = strlen(s1);
25         get_next() ;
26         ///cout<<Next[len1]<<"***"<<endl;
27         if(len1%(len1-Next[len1])) {
28             printf("1
") ;
29         } else {
30             printf("%d
",(len1-Next[len1])) ;
31         }
32     }
33 }
K

L

题意:求n*(n + 1) / 2。

思路:直接求。。。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int T ;
 7     cin >>T ;
 8     while(T--) {
 9        int64_t n ;
10        scanf("%lld",&n) ;
11        printf("%lld
",n*(n+1)/2);
12     }
13 }
L
原文地址:https://www.cnblogs.com/love-fromAtoZ/p/10649520.html