USACO section 1.1 C++题解

USACO section1.1:
DONE 2017.03.03 TEXT Submitting Solutions
DONE 2017.03.04 PROB Your Ride Is Here [ANALYSIS]
DONE 2017.03.04 TEXT Contest Problem Types
DONE 2017.03.04 TEXT Ad Hoc Problems
DONE 2017.03.04 PROB Greedy Gift Givers [ANALYSIS]
DONE 2017.03.04 PROB Friday the Thirteenth [ANALYSIS]
DONE 2017.03.04 PROB Broken Necklace [ANALYSIS]
由上可见section1.1中共有四道题,没有考察算法,只是单纯看思考是否到位以及细心程度。ios

Prob1:Your Ride Is Here(水题)
题意:input给出两个所有由大写字母组成的单词, 每一个字母对应一个数字(A-1,B-2……),
两个单词中的字母分别相乘,获得两个数字, 判断这两个数字%47的余数是否相等。算法

NOTE:因为数据很小,无须担忧溢出,可是保险起见,仍是在每次运算的过程当中取余。(a%b)*(c%b) = (a*c)%b;数组

源代码:ide

 1 /*
 2 ID:kongse_1
 3 PROG:ride
 4 LANG:C++ 
 5 */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 using namespace std;
10 const int MOD = 47;
11 string a, b;
12 int num1=1 ,num2=1;
13 int main()
14 15  freopen("ride.in", "r", stdin);
16  freopen("ride.out", "w", stdout);
17  cin >> a >> b;
18  
19  for(int i = 0; i != a.size(); ++i)
20   num1 = (num1*(a[i]-'A'+1))%MOD;
21  for(int i = 0; i != b.size(); ++i)
22   num2 = (num2*(b[i]-'A'+1))%MOD;
23  
24  if(num1 == num2) cout << "GO" << endl;
25  else cout << "STAY" << endl;
26  fclose(stdin);
27  fclose(stdout);
28  return 0;
29 }


Prob2:Greedy Gift Givers (水题)
题意:有n我的,没人开始身上有0块钱,每一个人选择掏出x的钱给他指定的n我的买礼物,他指定的人每一个人获得x/n块钱,若除不尽(x%n)则多出来的零钱归他本身。输出一轮以后每一个人对应的钱数(能够是负的...)。spa

P.S:原本开始想要用map作一一映射,结果map自带排序,把原来输入的顺序搞没了,因而乎只能拿俩数组维护。code

源代码:blog

 1 /*
 2 ID:kongse_1
 3 PROG:gift1
 4 LANG:C++
 5 */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <algorithm>
 9 #include <cstring>
10 using namespace std;
11 const int maxn = 15;
12 string x[maxn], y[maxn], z;
13 int num, sum, n, money[maxn];
14 int find_(string curr)
15 {
16  for(int i = 0; i != num; ++i)
17  {
18   if(x[i] == curr) return i;
19  }
20 }
21 void calculate_(int a, int b)
22 {
23  money[a] -= b;
24  return ;
25 }
26 int main(){
27  freopen("gift1.in", "r", stdin);
28  freopen("gift1.out", "w", stdout);
29  
30  cin >> num;
31  
32  for(int i = 0; i != num; ++i)
33  {
34   cin >> x[i];
35  }
36  
37  for(int i = 0; i != num; ++i)
38  {
39   cin >> z >> sum >> n; 
40   if(n)
41   {
42    calculate_(find_(z), sum-sum%n);
43    for(int j = 0; j != n; ++j)
44    {
45     cin >> y[j];
46     calculate_(find_(y[j]), -sum/n);
47    } 
48   }
49  }
50  
51  for(int i = 0; i != num; ++i)
52  {
53   cout << x[i] << " " << money[i] << endl;
54  }
55  fclose(stdin);
56  fclose(stdout);
57  return 0;
58 }

 


Prob3:Friday the Thirteenth
题意:已知1900年1月1日是周一,统计包括1900年在内的N年间,每个月13号是周一——周日的次数。排序


NOTE1:获得1900年1月13日是周六,根据每月的天数算出下一个月13日是星期几,注意判断闰年便可。队列

NOTE2:若是按照每一年做为单位一步步求,会出现一个问题:每年算的第12次实际上算的是下一年的1月13日(+31便是度过了12月份到了一月),因此算的最后一年的循环要特判。
源代码:ci

 1 /*
 2 ID:kongse_1
 3 PROG:friday
 4 LANG:C++
 5 */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 using namespace std;
10 const int maxn = 15;
11 int month[maxn]={0,31,28,31,30,31,30,31,31,30,31,30,31}, N, times[maxn], curr = 6;
12 int whether(int year)
13 {
14  if(year%400 == 0 || (year%4 == 0 && year%100 != 0)) return 1;
15  return 0;
16 }
17 void caculate_(int year)
18 {
19  if(year == 1900+N) return ;
20  
21  if(whether(year)) month[2] = 29;
22  else month[2] = 28;
23  
24  for(int i = 1; i != 13; ++i)
25  {
26   curr = (curr+month[i])%7;
27   if(i == 12 && year == 1900+N-1break;
28   ++times[curr];
29  }
30  caculate_(year+1);
31 }
32 int main()
33 {
34  freopen("friday.in", "r", stdin);
35  freopen("friday.out", "w", stdout);
36  
37  cin >> N;
38  
39  ++times[6];
40  caculate_(1900);
41  
42  cout << times[6] << " ";
43  for(int i = 0; i != 6; ++i)
44  {
45   cout << times[i];
46   if(i != 5) cout << " ";
47  }
48  cout << endl;
49  
50  fclose(stdin);
51  fclose(stdout);
52  return 0;
53


Prob4:Broken Necklace(有点意思)
题意:一串项链有三种颜色:红(r),蓝(b),白(w)。从中间某一处断开,从断开的两边分别去从头取颜色相同的珠子(两边右的可摘取数,而后从两个序列中找到a[i]+b[i+1]最大值(由于是从中间断的两川,因此必定是相邻的且向左的是第i个,向右的是第(i+1)%n)个。(注意,这是一串项链,首尾相连,是个循环队列)。

而算出没一个的向左区和向右取的值也很简单,不须要每一个都算,例如算出第i个能够向左取m个,那么第(i-1)个,即他的左边必定只能取(m-1)个(m!=1),m = 1即只有本身。当出现左边的颜色与当前颜色不一样时再从新计算。可是有一个例外。

咱们观察这样的一串:bbwbwrrwrwr 第一个b是5,第五个w则应该是1,可是事实上第五个应该是7,由于它跟右边的红色也能够相连。因此咱们获得特判:当上一个是2而且当前是白色(w)时应从新计算(即w是某队队尾)。

源代码:

 1 /*
 2 ID:kongse_1
 3 PROG:beads
 4 LANG:C++
 5 */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <algorithm>
10 #include <cstdlib>
11 using namespace std;
12 const int maxn = 505;
13 string x;
14 int n, num[2][maxn], max_;
15 int whether(char a, char b)
16 {
17  if(a+b == 'r'+'b'return 1;
18  return 0;
19 }
20 void calculate_(int curr, string y)
21 {
22  char last = x[curr];
23  if(y == "left")
24  {
25   int wh = 1;
26   num[wh][curr] = 1;
27   for(int i = (curr-1+n)%n;i != curr ; i = (i-1+n)%n)
28   {
29    if(x[i] == last || x[i] == 'w' || last == 'w')
30    {
31     if(last == 'w') last = x[i];
32     ++num[wh][curr];
33    }
34    else break;  
35   }
36  }
37  
38  else
39  {
40   int wh = 0;
41   num[wh][curr] = 1;
42   for(int i = (curr+1)%n; i != curr ; i = (i+1+n)%n)
43   {
44    if(x[i] == last || x[i] == 'w' || last == 'w')
45    {
46     if(last == 'w') last = x[i];
47     ++num[wh][curr];
48    }
49    else break;
50   }
51  }
52  return ;
53 }
54 int main()
55 {
56  freopen("beads.in", "r", stdin);
57  freopen("beads.out", "w", stdout);
58  
59  cin >> n >> x; 
60  
61  for(int i = 0; i != n; ++i)
62  {
63   if( !i || (num[0][(i-1+n)%n] == 2 && x[i] == 'w') || whether(x[(i-1+n)%n],x[i]) )
64    calculate_(i, "right");
65    else num[0][i] = num[0][i-1]-1;
66  }
67  
68  for(int i = n-1; i != -1; --i)
69  {
70   if( i == n-1 || (num[1][(i+1)%n] == 2 && x[i] == 'w') || whether(x[(i+1)%n],x[i]) )
71    calculate_(i, "left");
72   else num[1][i] = num[1][i+1]-1;
73  }
74  
75  for(int i = 0; i != n; ++i){
76  
77   max_ = max(max_, num[0][i]+num[1][(i-1+n)%n] ); 
78  }
79  
80  cout <<((max_<n)?max_:n) << endl;
81  
82  fclose(stdin);
83  fclose(stdout);
84   
85  return 0;
86 }


自此,USACO section1.1便所有完成了。
箜瑟_qi 2016.03.04

相关文章
相关标签/搜索