upc 2020春季个人训练赛第二场(高精+模拟)

问题 A: 【高精度】简单计算

题目描述
计算机的基本功能是计算,作为一个计算机爱好者,Ivy当然知道如何编写一个计算机程序,让计算机能进行简单的计算。
之所以简单,因为Ivy的程序只需根据输入的两个正整数,根据要求计算这两个数的和或者差即可(所有输入数据确保x>=y)。
输入
输入共有三行。第一行包含一个正整数x,第二行包含一个正整数y,第三行包含一个算术运算符(加号或者减号)。

输出
只有一行,表示将输入的两个正整数根据运算符进行计算后所得结果(两数之和或者之差)。

样例输入 Copy
251
249
+
样例输出 Copy
500
提示
对于60%的数据,1<=x,y<=16383;
对于80%的数据,1<=x,y<=1073741823;
对于90%的数据,1<=x,y<=4*1019
对于100%的数据,1<=x,y<=1030。

思路:
直接套用高精度的模板即可

string s1,s2;
int a[maxn],b[maxn],c[maxn];
int alen,blen,len;
char p;
bool f = 0;//记录结果为正还是为负 
bool compare(int alen,int blen)
//比较一下两个串的大小,只能大数减小数 
{
    if(alen < blen) return true;
    if(alen == blen) return s1 < s2;
    return false;
}
 
void addition(string s1,string s2)
{
    memset(c,0,sizeof(c));
    alen = s1.size();
    blen = s2.size();
    for(int i=1;i<=alen;i++) a[i] = s1[alen-i]-'0';
    for(int i=1;i<=blen;i++) b[i] = s2[blen-i]-'0';
    int x = 0;//进位 
    if(alen < blen)  swap(alen,blen);
    for(int i=1;i<=alen+1;i++)
    {
        c[i] = a[i]+b[i]+x;
        x = c[i]/10;
        c[i] %= 10;
    }
    len = alen+1;
    while(c[len] == 0 && len > 1)    len--;
    for(int i=len;i>=1;i--)
        printf("%d",c[i]);
    printf("\n");
}
 
void jianfa(string s1,string s2)
{
    int alen = s1.size();
    int blen = s2.size();
    if(compare(alen,blen))
    {
        swap(s1,s2);
        f = 1;
    }
    alen = s1.size();
    blen = s2.size();
    for(int i=1;i<=alen;i++) a[i] = s1[alen-i]-'0';
    for(int i=1;i<=blen;i++) b[i] = s2[blen-i]-'0';
    //转换成数字存入数组中 
    for(int i=1;i<=alen;i++)
    {
        if(a[i] < b[i])//这一位数字不够减
        {
            a[i+1]--;//借位,后一位-1,这一位+10 
            a[i] += 10;
         }
        c[i] = a[i]-b[i];//相减 
    }
    int len = alen;
    while(len >= 1 && c[len] == 0) len--;//去掉前导零 
    if(len < 1) printf("0");
    //如果最后长度小于1,说明结果为0,直接输出0
    if(f)   printf("-");
    //如果进行交换,说明被减数小于减数,输出负号 
    for(int i=len;i>=1;i--)
        printf("%d",c[i]);
    printf("\n");
}
 
int main()
{
    cin >> s1 >> s2;
    cin >> p;
    if(p == '+')    addition(s1,s2);
    else    jianfa(s1,s2);
    return 0;
}

问题 B: 【模拟】步步夺金

题目描述
Ivy所在的公司想推出一款手机APP“步步夺金”,该APP可以统计用户每天走路的步数,并给予相应的“金币”奖励。在用户的“金币”达到一定数量后,就可以在公司的网站上兑换一定的体育用品。
根据走路步数x奖励金币的规则如下:
1、每天的前1000步可领取0.3金币(若未达到1000步则领取数量为零),之后的每2000步能领取0.1金币。为了引导用户适量运动,每天领取的金币数量不能超过3。
2、用户只有在APP中点击“签到”才能领取当天步数对应的金币。
3、为了让用户能够每天坚持使用该APP,在用户连续三天签到后,从第四天开始,用户每天“签到”时领取的金币数可以在原金币计算方法的基础上乘以2(当然前提是在第四天时用户也点击“签到”,并且领的金币最多不能超过6)。但之后只要有一天中断点击“签到”,则又要重新连续签到三天,在第四天时才能继续获得金币加倍的优惠。
Ivy的任务是,根据用户每天所走步数以及签到的情况,统计用户n天后所拥有的金币总数。请帮助Ivy设计这个程序。
输入
输入共有n+1行,第一行包含一个正整数n,表示需要统计该用户n天后的金币总数。接下来有n(1<=n<=100)行,每行两个正整数,xi(1<=xi<=100000)和fi(1或0),分别表示第i天时用户所走的步数以及当天该用户是否进行了签到。fi为0表示用户当天未点击“签到”,为1表示用户当天点击“签到”。
输出
输出数据仅一行,表示n天后该用户所拥有的金币总数,保留一位小数。
样例输入 Copy
6
600 1
2300 1
5000 1
56000 1
80000 0
57000 1
样例输出 Copy
9.8
提示
第一天:用户走了600步,小于1000步,签到后得到0金币。
第二天:用户走了2300步,前1000步可得金币0.3;2300-1000=1300,不足2000步。所以签到后可得0.3金币。
第三天:用户走了5000步,在进行签到后,可得到的金币为:0.3+0.12=0.5。
第四天:用户走了56000步,在进行签到后,应得的金币为: 0.3+0.1
27=3。由于是连续第四天签到,所以实际得到32=6金币。
第五天:用户走了80000步,但未进行签到,所以得到的金币为0。
第六天:用户走了57000步,进行签到后,应得的金币为::0.3+0.1
28=3.1。由于每天最高获金不能超过3,所以实际得到3金币。
根据上述每天获得的金币,该用户6天后可获“金币”总数为9.8。

思路:
模拟。
按照题目要求一步步实现就可以

int n;
double ans,sum;
struct node
{
	int x,f;
}a[105];

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%d%d",&a[i].x,&a[i].f);
		if(a[i].x >= 1000 && a[i].f == 1)
		{
			sum += 0.3+((a[i].x-1000)/2000)*0.1;
			if(i+1 <= 3)
			{
				ans += sum>3?3:sum;	
				sum = 0;
				continue;
			}
			if(a[i-1].f == 1 && a[i-2].f == 1 && a[i-3].f == 1)
			//连续签到四天且第四天也签到 
			{
				sum = sum*2;
				ans += sum>6?6:sum;	
				sum = 0;//先加上,然后置零 
				continue;
			}
		}
		//判断每天的金币是否大于3 
		ans += sum>3?3:sum;
		sum = 0;
	}
	printf("%.1f\n",ans);
	return 0;
}

问题 C: 【模拟】工资和税收

题目描述
由于Ivy程序设计能力超强,所以被NBA联盟看中并为其工作。Ivy的主要工作是根据联盟需要开发程序。今天Ivy要编写的程序是资金预算。
按照NBA联盟规定,每个球队的工资总额一旦超过奢侈税起征点,超出的部分就将按1比1征税。也就是说每超出1美元,就要支付给联盟1美元奢侈税。比如说起征点是6000万美元,而球队付给球员的工资总额是7000万美元,那么球队在工资上将要花费8000万美元(其中支付球员的工资是7000万美元,而支付给联盟的奢侈税是1000万美元)。
Ivy因有其他更重要的事情,所以想请你帮她编写该程序。该程序的功能是:输入某个球队当年每个球员的应得工资,计算并输出该球队花费在球员工资方面的总金额(包括付给球员的工资以及可能产生的奢侈税)。
输入
第一行是一个整数,表示奢侈税起征点(单位:美元)
第二行是球队的名字
第三行是一个整数n,表示该球队有n(8<=n<=18)名球员。
接下来有n行,每行包括1名球员的名字和工资(单位:美元),名字和工资之间用1个空格分开。球员的名字由两个单词组成,分别表示名和姓,名和姓之间也用1个空格分开。每名球员的工资是一个不超过4000万的整数。
输出
输出只有一行,该行只有一个整数,表示该球队当年花费在工资方面的总金额(包括应付球员的工资以及可能产生的奢侈税)。
样例输入 Copy
61700000
Houston
15
Tracy McGrady 15694250
Juwan Howard 5900400
Dikembe Mutombo 5811043
Yao Ming 5594906
Stromile Swift 5000000
David Wesley 4950000
Moochie Norris 4200000
Vin Baker 3850000
Bob Sura 3520000
Mike James 3300000
Charlie Ward 1873300
Jon Barry 1800000
Luther Head 975600
Ryan Bowen 900498
Toraye Braggs 719373
样例输出 Copy
66478740

思路:
模拟。
按照题目要求实现就可以,把每个人的工资加和,如果大于奢侈税起征点就再加上1:1的税收即可
卡了我好多遍的是球队的名字,名字可能是好多个单词,需要先getchar()一下,然后getline(cin,s)输入一行

补充一下string类吧

string s;	//生成一个空字符串
string s(str);	//可以复制str到s中
cin >> s;	//读取单词
getline(cin,s);	//读取一行
s.size();	//获得字符串的长度
一定要注意使用getchar()

看代码吧

ll n,v,ans;
string s;
struct node
{
	char s1[25],s2[25];
	ll w;
}a[20];

int main()
{
	cin >> v;
	getchar();
	getline(cin,s);
	//getchar();
	cin >> n;
	for(int i=0;i<n;i++)
	{
		scanf("%s",a[i].s1);
		scanf("%s",a[i].s2);
		cin >> a[i].w;
		ans += a[i].w;
	}
	if(ans > v)
		ans += ans-v;
	cout << ans << endl;
	return 0;
}

问题 D: 沙盘游戏

题目描述
Ivy是如此地喜欢编程,以至于在面对游戏时也是如此。在沙盘游戏中有一个巨大的方形沙盘(长方形或者正方形),该沙盘被分隔成边长为1的小方格,每个小方格内有一个整数。沙盘玩家需要在沙盘中圈出一个方形(长方形或者正方形都可以)的区域(必须沿着小方格的边界划线,不能穿过小方格的内部),目标是争取被圈区域内的整数之和最大。
为了描述方便,Ivy把这个沙盘用nm个整数来表示,每个整数所在位置表示沙盘中一个边长为1的小方格。
Ivy现在需要编程解决这样一个问题:在n
m(n行m列)个整数中选择一个xy(x行y列)的方形区域(x最大可达n,y最大可达m),使得这xy个整数之和是所有可以选择的方形区域中最大的,并输出这个最大总和值。
输入
第一行包含n和m二个整数,中间用一个空格分隔,分别表示原始方形区域中所包含的行数和列数。
下面有n行,每行m个整数(每个整数的范围是-200到200)组成的数据。
输出
一行一个整数,表示某个被圈出的方形区域中所有位置上整数之和,该值必须是所有可以圈出的方形区域所对应整数和中,总和最大的那个,该值确保不超过106 。
样例输入 Copy
3 3
10 -21 9
7 8 4
-6 1 0
样例输出 Copy
19
提示
圈出的方形区域是第二行的3个整数,即7、8、4,此三数之和为19,为所有可圈出区域中整数之和的最大值。

对于10%的数据,n,m<=5
对于40%的数据,n,m<=30
对于60%的数据,n,m<=40
对于90%的数据,n,m<=80
对于100%的数据,n,m<=280

int main()
{
    int s[300][300];
    int a[300][300];
    memset(s,0,sizeof(s));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            scanf("%d",&a[i][j]);
            s[i][j]+=a[i][j];
            s[i][j]+=s[i-1][j];
            s[i][j]+=s[i][j-1];
            s[i][j]-=s[i-1][j-1];
        }
    }
    int maxx=-1e8;
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<i; j++)
        {
            int rec=0;
            for(int w=1; w<=m; w++)
            {
                if(s[i][w]-s[j][w]-s[i][rec]+s[j][rec]>0)
                {
                    if(s[i][w]-s[j][w]-s[i][rec]+s[j][rec]>maxx)
                    {
                        maxx=s[i][w]-s[j][w]-s[i][rec]+s[j][rec];
                    }
                }
                else
                {
                    if(s[i][w]-s[j][w]-s[i][rec]+s[j][rec]>maxx)
                    {
                        maxx=s[i][w]-s[j][w]-s[i][rec]+s[j][rec];
                    }
                    rec=w;
                }
            }
        }
    }
    printf("%d\n",maxx);
    return 0;
}

问题 E: 求和为C

题目描述
楠楠在网上刷题,感觉第一题:求两数的和(A+B Problem)太无聊了,于是增加了一题:求和为C的Problem,难倒了一群小朋友,哈哈。
题目是这样的:给出N个正整数,一个值C,要求在这N个整数中找一段连续的数(至少2个数),使得它们的和等于C,问这样的方案有多少种?
例如:N=8,C=7,8个整数是:2 5 1 1 2 4 7 1。答案是3。具体方案:(2, 5)、(5,1,1)、(1,2,4)。
输入
第一行2个正整数:N,C。
第二行:N个正整数。
输出
一个整数,表示该串数中包含的所有方案数。
样例输入 Copy
4 5
1 4 1 4
样例输出 Copy
3
提示
N的范围是[1…100,000]。
C的范围是[1…1,000,000,000]。
N个整数中每个数的范围是:[1…1,000,000,000]。

ll n,c,ans,cnt;
ll s[100010];
deque<ll> q;
int main()
{
	cin >> n >> c;
	for(i=1;i<=n;i++)
	{
		cin >> s[i];
		s[i] += s[i-1];//记录前缀和 
	}
	for(i=1;i<=n;i++)
	{
		while(q.size() >= 1)
		{
			
			ans = s[i]-s[q.front()-1];
			if(ans < c) break;
			else
			{
				if(ans == c) cnt++;
				q.pop_front();
			}
		}	
		q.push_back(i);
	}
	printf("%lld",cnt);
	return 0;
}

问题 F: 孤立的棋子

题目描述
在n*n的方格棋盘上,有一些格子里有棋子。如果一个棋子的上、下、左、右、左上、左下、右上、右下没有其它棋子,就称是孤立的,问棋盘上有多少孤立的棋子?
输入
第一行1个正整数:N,范围在[1,20]。
下面有N行,每行N个整数,要么是0,要么是1。0表示没有棋子,1表示有棋子。
输出
一个整数,表示棋盘上有多少孤立的棋子。
样例输入 Copy
4
1 0 1 0
0 0 1 0
0 1 0 1
0 0 0 0
样例输出 Copy
1

思路:
首先把棋盘上有的棋子数量记录下来sum,然后针对每个棋子,如果其八个方向一旦有一个有棋子,那就记录下来cnt,最后sum - cnt即可

int n,ans,sum,cnt;
int a[25][25];
int dx[8] = {0,0,-1,1,-1,-1,1,1};
int dy[8] = {1,-1,0,0,1,-1,1,-1};
int main()
{
    cin >> n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            cin >> a[i][j];
            if(a[i][j] == 1)
                sum++;
        }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(a[i][j] == 1)
            {
                for(int k=0;k<8;k++)
                {
                    if(a[i+dx[k]][j+dy[k]] == 1)
                    {
                        cnt++;  break;
                    }
                }
            }
        }
    }
    cout << sum-cnt << endl;
    return 0;
}
发布了58 篇原创文章 · 获赞 0 · 访问量 1619

猜你喜欢

转载自blog.csdn.net/magic_wenge/article/details/105282141
UPC