USACO training 1.1 with C++


USACO training 1.1


Your Ride Is Here (EASY)

Acwing
题意: 判断两个给定字符在字母序之积意义下是否同余。
分析: 只需要分别计算出两者即可
代码如下:

#include 
#include 
//#define Uint unsigned int
using namespace std;
int main(void){
     
string a;
unsigned int n,ans_1 = 1,ans_2 = 1;
cin >> a;
n = a.length();
    for(unsigned int i=0;i<n;++i){
     
        ans_1 *= a[i]-'A'+1;}
cin >> a;
n = a.length();
    for(unsigned int i=0;i<n;++i){
     
        ans_2 *= a[i]-'A'+1;}
if(ans_1%47 == ans_2%47)
    printf("GO\n");
else
    printf("STAY\n");
return 0;}

Greedy Gift Givers (MIDDLE-)

Acwing
题意: 有一堆名字相互送了礼物,求最终的净收入
分析: 建立 结构体 或者 map ,处理好输入即可。要判断有没有送礼人、有没有送礼。之后需要两次循环分别计算支出和收入,为了避免被多减了,我定义了一个 bool 进行判断。题目要i求向下取整,可以先除 int 再乘 int 实现。
代码如下( struct ):

#include 
using namespace std;
struct giver{
     
	string name;
	int money;
}arr[12];
string Name,names;
int n,Money,Nums;
bool flag = false;
int main(void){
     
	cin >> n;
	for(int i=1;i<=n;++i)
		cin >> arr[i].name;
	for(int i=1;i<=n;++i){
     
		flag = true;
		cin >> Name >> Money >> Nums;
		if(!Nums || !Money)
			continue;
		for(int j=1;j<=Nums;++j){
     
			cin >> names;
			for(int k=1;k<=n;++k){
     
				if(flag && arr[k].name == Name){
     
					flag = false;
					arr[k].money -= Money/Nums*Nums;}
				if(arr[k].name == names)
					arr[k].money += Money/Nums;}}}
	for(int i=1;i<=n;++i)
		cout << arr[i].name << " " << arr[i].money << endl;
return 0;}

使用(map),是一样的思路 不过可以写得好看一点点

#include 
map<string,int> a;
//a[name],a[s]

代码如下( map )(其实是队长写的…):

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 50007;
int n, m;
map<string, int>mp;
string names[N];
int main(){
     
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
     
        string s;
        cin >> s;
        names[i] = s;
        mp[s] = 0;}
    for(int i = 1; i <= n; ++ i){
     
        int money, num;
        string s;
        cin >> s;
        scanf("%d%d", &money, &num);
        int remain = 0;
        if(num)
			remain = money - (money / num) * num;
        money -= remain;
        mp[s] -= money;
        for(int j = 1; j <= num; ++ j){
     
            string name;
            cin >> name;
            mp[name] += money / num;}}
    for(int i = 1; i <= n; ++ i)
        cout << names[i] << " " << mp[names[i]] << endl;
return 0;}

Friday the 13th (MIDDLE-)

Acwing
题意: 计算从1900年元旦(周一)到给定年份元旦前夕之间出现过的周六、周日…在13日出现的次数
分析: 首先就是判断闰年,其次需要推算出13号所对应的星期数…如果不直接刚模拟,其实很容易得出这样的一个公式(x+a)%7+1 就是 x 经过 a 天后的星期数。接着,记得输出的顺序。
代码如下:

#include 
const int days[13]={
     0,31,28,31,30,31,30,31,31,30,31,30,31};
int n,count[8];
int main(){
     
	int Day = 6;
	scanf("%d",&n);
	for(int i=1900;i<=1900+n-1;i++){
     
		for(int j=1;j<=12;++j){
     
			++count[Day];
			if(j==2&&!(i%4)&&(i%100||!(i%400)))
				Day = (Day+1-1)%7 + 1;
			Day = (Day+days[j]-1)%7 + 1;}}
			
	printf("%d %d ",count[6],count[7]);
	for(int i=1;i<5;i++)
		printf("%d ",count[i]);
	printf("%d",count[5]);
return 0;}

另外,求任意给定的日期的星期数可以使用W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7 被称作基姆拉尔森计算公式


Broken Necklace (MIDDLE-)

Acwing
题意: 寻找给定字符串中最长的同名字符(w被视作任意的)
分析: 顺序遍历+倒序遍历,即为所求。不过要注意到最终的答案有可能超过总长度,因此取其中较小的作为答案即可。

#include 
#include 
using namespace std;
int main(){
     
    int n;
    //cin >> n;
    char s[405];
	scanf("%d\n%[rbw]",&n,s);
    int ans = 0;
    for(int i=0;i<n;++i){
     
   		int b_cnt = 0;
   		for(int j=0; j<n;++j){
     
	   			if(s[(i-j+n)%n] == 'r')
				   	break;
	   			else
				   	++b_cnt;}
   		int r_cnt = 0;
   		for(int j=0;j<n;++j){
     
	   			if(s[(i-j+n)%n] == 'b')
				   	break;
	   			else
				   	++r_cnt;}
   		int left = max(b_cnt, r_cnt);

   	    b_cnt = 0;
   		for(int j=1;j<=n;++j) {
     
	   			if (s[(i+j)%n] == 'r')
				   	break;
	   			else
					++b_cnt;}
   		r_cnt  = 0;
   		for(int j=1;j<=n;++j){
     
	   			if(s[(i+j)%n] == 'b')
				   break;
	   			else
				   ++r_cnt;}
   		int right = max(b_cnt, r_cnt);

   		ans = max(ans,left+right);}
   	cout << min(ans,n);
return 0;}

TO BE CONTINUED…

你可能感兴趣的:(USACO,training,算法)