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中共有四道题,没有考察算法,只是单纯看思考是否到位以及细心程度。


Prob1:Your Ride Is Here(水题)

题意:input给出两个全部由大写字母组成的单词, 每个字母对应一个数字(A-1,B-2……),
两个单词中的字母分别相乘,得到两个数字, 判断这两个数字%47的余数是否相等。

NOTE:由于数据很小,无须担心溢出,但是保险起见,还是在每次运算的过程中取余。(a%b)*(c%b) = (a*c)%b;


源代码:

/*
ID:kongse_1
PROG:ride
LANG:C++ 
*/

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
using namespace std;

const int MOD = 47;

string a, b;
int num1=1 ,num2=1;

int main()
{	
	freopen("ride.in", "r", stdin);
	freopen("ride.out", "w", stdout);

	cin >> a >> b;
	
	for(int i = 0; i != a.size(); ++i)
		num1 = (num1*(a[i]-'A'+1))%MOD;

	for(int i = 0; i != b.size(); ++i)
		num2 = (num2*(b[i]-'A'+1))%MOD;
	
	if(num1 == num2)	cout << "GO" << endl;
	else cout << "STAY" << endl;

	fclose(stdin);
	fclose(stdout);
	return 0;
}
      
      
     
     
    
    


Prob2:Greedy Gift Givers (水题)

题意有n个人,没人开始身上有0块钱,每个人选择掏出x的钱给他指定的n个人买礼物,他指定的人每个人得到x/n块钱,若除不尽(x%n)则多出来的零钱归他自己。输出一轮之后每个人对应的钱数(可以是负的...)。


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


源代码:

/*
ID:kongse_1
PROG:gift1
LANG:C++
*/

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
using namespace std;

const int maxn = 15;

string x[maxn], y[maxn], z;
int num, sum, n, money[maxn];
int find_(string curr)
{
	for(int i = 0; i != num; ++i)
	{
		if(x[i] == curr)	return i;
	}
}

void calculate_(int a, int b)
{
	money[a] -= b;
	return ;
}

int main(){
	freopen("gift1.in", "r", stdin);
	freopen("gift1.out", "w", stdout);
	
	cin >> num;
	
	for(int i = 0; i != num; ++i)
	{
		cin >> x[i];
	}
	
	for(int i = 0; i != num; ++i)
	{
		cin >> z >> sum >> n;	
		if(n)
		{
			calculate_(find_(z), sum-sum%n);
			for(int j = 0; j != n; ++j)
			{
				cin >> y[j];
				calculate_(find_(y[j]), -sum/n);
			}	
		}
	}
	
	for(int i = 0; i != num; ++i)
	{
		cout << x[i] << " " << money[i] << endl;
	}

	fclose(stdin);
	fclose(stdout);
	return 0;
}
       
       
      
      
     
     
    
    


Prob3Friday the Thirteenth(有一小点坑,造成WA的后果,离AC只差一个数...)
题意:已知1900年1月1日是周一,统计包括1900年在内的N年间,每月13号是周一——周日的次数。

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


NOTE2:如果按照每年作为单位一步步求,会出现一个问题:每一年算的第12次实际上算的是下一年的1月13日(+31即是度过了12月份到了一月),所以算的最后一年的循环要特判。

源代码:

/*
ID:kongse_1
PROG:friday
LANG:C++
*/

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
using namespace std;

const int maxn = 15;

int month[maxn]={0,31,28,31,30,31,30,31,31,30,31,30,31}, N, times[maxn], curr = 6;

int whether(int year)
{
	if(year%400 == 0 || (year%4 == 0 && year%100 != 0))	return 1;
	return 0;
}

void caculate_(int year)
{
	if(year == 1900+N)	return ;
	
	if(whether(year))	month[2] = 29;
	else month[2] = 28;
	
	for(int i = 1; i != 13; ++i)
	{
		curr = (curr+month[i])%7;
		if(i == 12 && year == 1900+N-1)	break;
		++times[curr];
	}
	caculate_(year+1);
}
int main()
{
	freopen("friday.in", "r", stdin);
	freopen("friday.out", "w", stdout);
	
	cin >> N;
	
	++times[6];
	caculate_(1900);
	
	cout << times[6] << " ";
	for(int i = 0; i != 6; ++i)
	{
		cout << times[i];
		if(i != 5)	cout << " ";
	}
	cout << endl;
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}	
      
      
     
     
    
    


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是某队队尾)。

源代码:

/*
ID:kongse_1
PROG:beads
LANG:C++
*/

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          using namespace std; const int maxn = 505; string x; int n, num[2][maxn], max_; int whether(char a, char b) { if(a+b == 'r'+'b') return 1; return 0; } void calculate_(int curr, string y) { char last = x[curr]; if(y == "left") { int wh = 1; num[wh][curr] = 1; for(int i = (curr-1+n)%n;i != curr ; i = (i-1+n)%n) { if(x[i] == last || x[i] == 'w' || last == 'w') { if(last == 'w') last = x[i]; ++num[wh][curr]; } else break; } } else { int wh = 0; num[wh][curr] = 1; for(int i = (curr+1)%n; i != curr ; i = (i+1+n)%n) { if(x[i] == last || x[i] == 'w' || last == 'w') { if(last == 'w') last = x[i]; ++num[wh][curr]; } else break; } } return ; } int main() { freopen("beads.in", "r", stdin); freopen("beads.out", "w", stdout); cin >> n >> x; for(int i = 0; i != n; ++i) { if( !i || (num[0][(i-1+n)%n] == 2 && x[i] == 'w') || whether(x[(i-1+n)%n],x[i]) ) calculate_(i, "right"); else num[0][i] = num[0][i-1]-1; } for(int i = n-1; i != -1; --i) { if( i == n-1 || (num[1][(i+1)%n] == 2 && x[i] == 'w') || whether(x[(i+1)%n],x[i]) ) calculate_(i, "left"); else num[1][i] = num[1][i+1]-1; } for(int i = 0; i != n; ++i){ max_ = max(max_, num[0][i]+num[1][(i-1+n)%n] ); } cout <<((max_ 
         
           << endl; fclose(stdin); fclose(stdout); return 0; } 
          
        
       
       
      
      
     
     
    
    


自此,USACO section1.1便全部完成了。

箜瑟_qi 2016.03.04

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值