复习时食用,会比较简略。
目录
#10005. 「一本通 1.1 练习 1」数列极差
题目大意
一个由n个正整数组成的数列,每次擦去其中的两个数a和b。
然后在数列中加入一个数a*b+1,直至剩下一个数为止。
按这种操作方式最后得到的数中,最大的为max,最小的为min。
该数列的极差定义为M=max-min。
请对于给定的数列计算出相应的极差M。
对于全部数据,0<=n<=50000,保证所有数据计算均在32位有符号整数范围内。
题目分析
surprise!神奇的规律!
要得到max每次就擦掉最大的两个,要得到min每次就擦掉最小的两个。
进行多次试验寻找普遍规律。
肯定有什么证明方法,看我脑筋急转弯。还是不会。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,nn,x,a[50010],b[50010];
int cmp(int x,int y) { return x>y; }
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
a[i]=b[i]=x;
}
scanf("%d",&x);
sort(a+1,a+1+n,cmp); nn=n;
for(int i=1;i<=n-1;i++)//每次檫最大
{
a[1]=a[1]*a[2]+1;
a[2]=a[nn]; nn--;
sort(a+1,a+1+nn,cmp);
}
sort(b+1,b+1+n); nn=n;
for(int i=1;i<=n-1;i++)//每次擦最小
{
b[1]=b[1]*b[2]+1;
b[2]=b[nn]; nn--;
sort(b+1,b+1+nn);
}
printf("%d",b[1]-a[1]);
return 0;
}
#10006. 「一本通 1.1 练习 2」数列分段
题目大意
给定的一个长度为N的正整数数列A_i。
将其分成连续的若干段,使每段和不超过M,问最少能将其分成多少段。
对于20%的数据,有n<=10;
对于40%的数据,有n<=1000;
对于100%的数据,有n<=10^5,m<=10^9大于所有数的最大值。
题目分析
好水。
不懂就看代码ba。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n,m; scanf("%d%d",&n,&m);
int s=0,ans=0;
for(int i=1;i<=n;i++)
{
int x; scanf("%d",&x); s+=x;
if(s>m) { ans++; s=x; }//超过了
}
if(s) ans++;
printf("%d",ans);
return 0;
}
#10007. 「一本通 1.1 练习 3」线段
题目大意
有n条线段,选取其中k条线段使这k条线段没有重合部分,问k最大为多少。
对于20%的数据,n<=10;
对于50%的数据,n<=10^3;
对于70%的数据,n<=10^5;
对于100%的数据,n<=10^6,0<=ai<bi<10^6。
题目分析
回归例题1、2???
一段时间改成了一条线段。
一样要需要没有重合。
报告完毕。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int a,b;}a[1000010];
int cmp(node x,node y) { return x.b<y.b; }
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].a,&a[i].b);
sort(a+1,a+1+n,cmp);
int ans=1,end=a[1].b;
for(int i=2;i<=n;i++)
{
if(a[i].a>=end)
{
ans++; end=a[i].b;
}
}
printf("%d",ans);
return 0;
}
#10008. 「一本通 1.1 练习 4」家庭作业
题目大意
每个作业完成时间都是一天,在规定的时间内交上来的话才有学分。
找到一个完成作业的顺序获得最大学分。
对于20%的数据,n<=10^3;
对于40%的数据,n<=10^4;
对于60%的数据,n<=10^5;
对于100%的数据,n<=10^6,作业的完成期限均小于7*10^5
题目分析
回归例题5。
只要加一个小小小优化就好了。
而且这个优化很容易懂。
kk判断i和i之前的时间是否被填满,若已经填满了就不要去找了。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool f[700010],kk[700010];
struct node{int time,money;}a[1000010];
int cmp(node x,node y) { return x.money>y.money; }
int main()
{
int n; scanf("%d",&n);
memset(f,false,sizeof(f));
memset(kk,false,sizeof(kk));
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].time,&a[i].money);
sort(a+1,a+1+n,cmp);
int ans=0;
for(int i=1;i<=n;i++)
{
bool k=false;
for(int j=a[i].time;j>=1;j--)
{
if(kk[j]) break;
if(!f[j]) { f[j]=true; k=true; }
if(k) break;
}
if(k) ans+=a[i].money;
else kk[a[i].time]=true;
}
printf("%d",ans);
return 0;
}
#10009. 「一本通 1.1 练习 5」钓鱼
题目大意
有n个钓鱼湖,从左到右编号为1,2,…,n。希望利用H个小时钓到更多的鱼。
从1出发,向右走,可选择在湖边停留一定的时间钓鱼,最后在某一个湖边结束钓鱼。
从第i个湖到第i+1个湖需要走5*T_i分钟,测出在第i个湖停留,第一个5分钟可以钓到F_i条鱼,以后再钓5分钟,钓到的鱼量减少D_i,若减少后的鱼量小于0,则鱼量为0。
没有其他因素影响钓到期望数量的鱼。求出最多能钓鱼的数量。
对于100%的数据,2<=n<=100,1<=h<=20。
题目分析
钓个鱼怎么这么多事。
枚举最远去到的鱼塘的位置,范围内的鱼塘任你挑,当然是钓最多的啊。
很好懂的吧。好暴力啊。
我果然还是太辣鸡了,如果鱼的数量是负的就不要钓了,傻吗还钓。
我才不会告诉你我小测的时候就错在这。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool f=false;
int n,h,s,t[110],ans=0;
struct node{int a,b;}a[110],b[110];
int cmp(node x,node y) { return x.a>y.a; }
int main()
{
scanf("%d%d",&n,&h);
for(int i=1;i<=n;i++) scanf("%d",&a[i].a);
for(int i=1;i<=n;i++) scanf("%d",&a[i].b);
h*=12; t[1]=0; s=n;//12个五分钟
for(int i=2;i<=n;i++)
{
int x; scanf("%d",&x);
t[i]=t[i-1]+x;//x个五分钟
if(!f&&t[i]>=h) f=true,s=i-1;//s表示最远能去到的鱼塘
}
for(int ed=1;ed<=s;ed++)
{
for(int i=1;i<=ed;i++) b[i]=a[i];
int tt=h-t[ed],kk=0;
while(tt--)//实在是很暴力了
{
sort(b+1,b+1+ed,cmp);
if(b[1].a<=0) break;
kk+=b[1].a; b[1].a-=b[1].b;
}
ans=max(ans,kk);
}
printf("%d",ans);
return 0;
}
#10010. 「一本通 1.1 练习 6」糖果传递
这道题已经尽我的洪荒之力写的详细了!!!(个人觉得很明白了昂)