第二周PTA笔记 均等笔+旋转骰子+两个日期相差天数
均等笔
n个人围成一圈,每人有ai支笔。每人可以向左右相邻的人传递笔,每人每次传递一支笔消耗的能量为1。求使所有人获得均等数量的笔的最小能量。
输入格式:
第一行一个整数n ,表示人的个数(30%的数据,n<=1000;100%的数据,n<=1e6)。
接下来n行,每行一个整数 ai。
输出格式:
输出一个整数,表示使所有人获得均等笔的最小能量。(答案保证可以用64位有符号整数存储)
输入样例:
4
1
2
5
4
输出样例:
4
通过这道题我了解了一下64位有符号与无符号类型的整数,还了解了一个数学结论“在数轴上有n个点,找出一个点x,使得她到各个点的距离和最小。则该点表示的数就是这n个数的中位数。”
发现了原题为P2512糖果传递再附上题解
主要是因为一开始时间超出了想要写下此篇随笔加深记忆
//错误部分的代码
for(i=0;i<n;i++)
{
if(i==0)x[i]=0;
if(i==n-1)x[i]=s-a[n-1];
else {
for(j=0;j<i;j++)
{
x[i]+=a[j];
}
x[i]-=i*s;
}
}
//修改之后
for(i=1;i<n;i++)
{
x[i]=x[i-1]-a[i-1]+s;
}
再附上完整代码吧
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
long long int a[1000005],x[1000005]={0};
int main()
{
int cmp(const void *c,const void *d);
int n,i,j;
long long int s=0,t,y=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
s+=a[i];
}
s/=n;
for(i=1;i<n;i++)
{
x[i]=x[i-1]-a[i-1]+s;
}
qsort(x,n,sizeof(long long int),cmp);
if(n%2==0)t=(x[n/2]+x[n/2-1])/2;
else t=x[n/2];
for(i=0;i<n;i++)
{
y+=abs(t-x[i]);
}
printf("%lld",y);
return 0;
}
int cmp(const void *c,const void *d)
{
return *(long long int*)c-*(long long int*)d;
}
旋转骰子
玛莎有n个骰子,每个骰子的6个面上都恰好有一个0到9之间的数字。
现在玛莎将利用这n个筛子来制作新数字。她把n个骰子摆成一排,然后从左到右查看骰子的上表面并读取,即可得到一个新数字。随后她不断的旋转每个骰子的面就可以得到不同的新数字。旋转骰子需要满足以下规则: 1、制作的数字不能包含前导零; 2、制作新数字时不需要使用所有的骰子; 3、使用骰子旋转,无法将数字9转换为数字6,反之亦然。
给定n个骰子,玛莎可以用它们构成从1到x的所有整数。玛莎想知道,对于给定的n个骰子,这个x的最大取值是多少呢?
输入格式:
第一行仅一个整数n,表示骰子的数量(1≤n≤3)。
接下来n行,每行包含6个整数a[i][j](0≤a[i][j]≤9),表示第i个骰子的第j个面上的数字。
输出格式:
输出一个整数,即最大数x,玛莎可以使用她的骰子构成数字从1到x。如果无法构成1,则输出0。
输入样例:
3
0 1 3 5 6 8
1 2 4 5 7 8
2 3 4 6 7 9
输出样例:
98
这道题初期对我最大的困难是题目看不懂,大学生还是该好好多读读语文哪,大致讲一下读懂了题目后对于题目的理解。输入每个🎲六个面的数,然后将这些数由1-x组数。就比如有一个🎲,其六个面上的数为0,1,2,3,5,6,则这组数据的x为3。刚开始也不知道怎么想的,脑子不清醒得很,一直理解不了题目意思。接下来脑海中进行一个很复杂的思路,因为复杂,所以我也无法用语言说出来了,哈哈,就来说说后来这个暴力而又有用的思路。
思路:假设第一个🎲的第一个数为a,第二个🎲的第一个数为b,可以组成两个数a乘以10+b,a+b乘以10,就这样将每一种情况都涉及到然后存入数组中,之后再进行排序,然后再从头到尾看,查找没有相邻的数字,得出x。
附上代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
int max(int b[],int r);//判断排序后的数在哪个地方不相邻的函数
int cmp(const void *c,const void *d);
int n,a[3][8],i,j,r=0,b[1000],x,flag=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<6;j++)
{
scanf("%d",&a[i][j]);
}
}
if(n==1){
for(i=0;i<5;i++)
{
for(j=0;j<5-i)
}
if(a[0][0]==1){
for(i=1;i<6;i++)
{
if(a[0][i]!=i+1){
printf("%d",i);
return 0;
}
}
printf("%d",a[0][5]);
}//当第一个数为1
else if(a[0][0]==0&&a[0][1]==1){
for(i=2;i<6;i++)
{
if(a[0][i]!=i){
printf("%d",i-1);
return 0;
}
}
printf("%d",a[0][5]);
}//当第二个数为1
else printf("0");
}//只有一个🎲的情况
else if(n==2){
for(i=0;i<6;i++)
{
if(a[0][i]!=0){
b[r]=a[0][i];
r++;
}
if(a[1][i]!=0){
b[r]=a[1][i];
r++;
}
}
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
if(a[0][i]*10+a[1][j]!=0){
b[r]=a[0][i]*10+a[1][j];
r++;
}
if(a[0][i]+a[1][j]*10!=0){
b[r]=a[0][i]+a[1][j]*10;
r++;
}
}
}
qsort(b,r,sizeof(int),cmp);
x=max(b,r);
printf("%d",x);
for(i=0;i<r;i++)
printf("%d\n",b[i]);}//有两个🎲的情况
else{
for(i=0;i<6;i++)
{
if(a[0][i]!=0){
b[r]=a[0][i];
r++;
}
if(a[1][i]!=0){
b[r]=a[1][i];
r++;
}
if(a[2][i]!=0){
b[r]=a[2][i];
r++;
}
}
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
if(a[0][i]*10+a[1][j]!=0){
b[r]=a[0][i]*10+a[1][j];
r++;
}
if(a[0][i]+a[1][j]*10!=0){
b[r]=a[0][i]+a[1][j]*10;
r++;
}
}
}
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
if(a[0][i]*10+a[2][j]!=0){
b[r]=a[0][i]*10+a[2][j];
r++;
}
if(a[0][i]+a[2][j]*10!=0){
b[r]=a[0][i]+a[2][j]*10;
r++;
}
}
}
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
if(a[1][i]*10+a[2][j]!=0){
b[r]=a[1][i]*10+a[2][j];
r++;
}
if(a[1][i]+a[2][j]*10!=0){
b[r]=a[1][i]+a[2][j]*10;
r++;
}
}
}
qsort(b,r,sizeof(int),cmp);
x=max(b,r);
printf("%d",x);
}//三个🎲的情况
return 0;
}
int cmp(const void *c,const void *d)
{
return *(int*)c-*(int*)d;
}
int max(int b[],int r)
{
int i;
for(i=0;i<r-1;i++)
{
if(i==0){
if(b[i]!=1)return 0;
}
if(b[i+1]-b[i]!=1&&b[i+1]-b[i]!=0)return b[i];//这个地方的“并”一开始写成了“或”,然后只过了一个点
}
return b[r-1];
}
相比于最初代码改进的地方还有对于得到的数是否为0的判断,这对于我写的函数有很大的影响。
这道题主要是锻炼了一下自己理解题目的能力哈哈哈,还有一些对小细节地方的处理。
两个日期相差天数
现在有两个不同的日期,你能告诉我它们之间差几天吗?
输入格式:
有多行数据,每行数据包含6个数字,中间用空格分隔,每3个数字代表一个日期。
输出格式:
对应于输入数据,输出数据有相同的行数,每行表示对应的两个日期相差的天数。
输入样例:
1934 2 4 2047 11 30
2192 10 3 1921 5 8
输出样例:
-41572
99130
这题不是太难,因为题目意思至少还可以理解,但是!有些小地方因为粗心写错了,就一直只过了两个点,就是那种很小不容易发现的地方啊,明明思路没错就是AC不了,真tm非常难受,曾一度想要爆粗口!!!
思路:我是将较小的年份月份天数算到另外一个较大年份的数据的月份天数,然后再对于天数具体处理。如果较小的年份在前,就天数正数来算,最后再加上负号。
附上代码:
#include<stdio.h>
#include<math.h>
int main()
{
long long int y1,m1,d1,y2,m2,d2,t=0,i,x;
while(scanf("%lld%lld%lld%lld%lld%lld",&y1,&m1,&d1,&y2,&m2,&d2)!=EOF){
if(y1>y2){
if(m2<=2){
for(i=y2;i<y1;i++)
{
if((i%4==0&&i%100!=0)||(i%400==0))t+=366;
else t+=365;
}
}
else{
for(i=y2+1;i<=y1;i++)
{
if((i%4==0&&i%100!=0)||(i%400==0))t+=366;
else t+=365;
}
}
if(m1>m2){
for(i=m2;i<m1;i++)
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)t+=31;
else if(i==4||i==6||i==9||i==11)t+=30;
else{
if((y1%4==0&&y1%100!=0)||(y1%400==0))t+=29;
else t+=28;
}
}
t=t-d2+d1;
}//ok
else if(m1==m2) t+=(d1-d2);//ok
else{
for(i=m1;i<m2;i++)
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)t-=31;
else if(i==4||i==6||i==9||i==11)t-=30;
else{
if((y1%4==0&&y1%100!=0)||(y1%400==0))t-=29;//修改处
else t-=28;
}
}
t=t-d2+d1;//ok
}
}
else if(y1==y2){
if(m1>m2){
for(i=m2;i<m1;i++)
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)t+=31;
else if(i==4||i==6||i==9||i==11)t+=30;
else{
if((y1%4==0&&y1%100!=0)||(y1%400==0))t+=29;//检查后修改处
else t+=28;
}
}
t=t-d2+d1;
}//ok
else if(m1==m2){
t=d1-d2;
}//修改处
else {
for(i=m1;i<m2;i++)
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)t-=31;
else if(i==4||i==6||i==9||i==11)t-=30;
else{
if((y2%4==0&&y2%100!=0)||(y2%400==0))t-=29;
else t-=28;
}
}
t=t+d1-d2;//ok
}
}
else{
if(m1<=2){
for(i=y1;i<y2;i++)
{
if((i%4==0&&i%100!=0)||(i%400==0))t+=366;
else t+=365;
}
}
else{
for(i=y1+1;i<=y2;i++)
{
if((i%4==0&&i%100!=0)||(i%400==0))t+=366;
else t+=365;
}
}
if(m1>m2){
for(i=m2;i<m1;i++)
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)t-=31;
else if(i==4||i==6||i==9||i==11)t-=30;
else{
if((y2%4==0&&y2%100!=0)||(y2%400==0))t-=29;
else t-=28;// if中的y1,y2数值一定要很注意,就是错在这个小地方
}
}
t=t-d1+d2;
}
else if(m1==m2) t+=(d2-d1);
else{
for(i=m1;i<m2;i++)
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)t+=31;
else if(i==4||i==6||i==9||i==11)t+=30;
else{
if((y2%4==0&&y2%100!=0)||(y2%400==0))t+=29;
else t+=28;
}
}
t=t-d1+d2;
}
t=-t;
}
printf("%lld\n",t);
t=0;
}
return 0;
}
之所以能查得出bug,必须得在此感谢ycy同学给我提供的代码,让我用他正确的代码测试数据,由此发现一个数据bug(2030 2 28 2000 3 1)。我所有的解题步骤也是自己拟定数据来具体计算,比较好理解。这题真的把我气得够呛!!!
以上是我这次遇到的自己感觉比较困难的题目