泉五培训Day3
T1 家庭作业
题目
【问题描述】
小P为了能高效完成作业,规定每项作业花一个单位时间。
他的学习日从0时刻开始,有100000个单位时间。在任一时刻,他都可以选择编号1~N的N项作业中的任意一项作业来完成。
因为他在每个单位时间里只能做一个作业,而每项作业又有一个截止日期,所以他很难有时间完成所有N个作业,虽然还是有可能。
对于第i个作业,有一个截止时间D_i,如果他可以完成这个作业,那么他可以获得分数P_i.
在给定的作业分数和截止时间下,小P能够获得的分数最大为多少呢?答案可能会超过32位整型。
【输入格式】(homework.in)
第1行:一个整数N.
第2~N+1行:第i+1行有两个用空格分开的整数:D_i和P_i.
【输出格式】(homework.out)
输出一行,里面有一个整数,表示最大获分值。
【样例输入】
3
2 10
1 5
1 7
【样例输出】
17
【样例解释】
第1个单位时间完成第3个作业(1,7),然后在第2个单位时间完成第1个作业(2,10)以达到最大分数
【数据范围】
对于前20%的数据,1 <= N <= 100.
对于前40%的数据,1 <= N <= 1000.
对于前60%的数据,1 <= N <= 20000.
对于100%的数据,1 <= N <= 100000,
1 <= D_i <= 100000,1 <= P_i <= 1000000000
解析
很明显这是一道贪心题。
只需按分数从小到大排序,再放到离结束时间最近且未被占用的时间,之后稍微优化一下便行了。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <algorithm> #include <iostream> #include <cstring> #include <string> #include <cstdio> using namespace std; const int N=100001; int n; long long ans; int f[N]; struct rec{ int d,p; }work[N]; bool cmp(rec a,rec b) { return a.p>b.p; } int find(int x) { if(f[x]<0) return x; return f[x]=find(f[x]); } int main() { memset(f,-1,sizeof(f)); cin>>n; for(int i=1;i<=n;i++) cin>>work[i].d>>work[i].p; sort(work+1,work+1+n,cmp); for(int i=1;i<=n;i++) { int r=find(work[i].d); if(r>0) ans+=1LL*work[i].p,f[r]=r-1; } cout<<ans; return 0; }
T2 方程式
题目
【题目描述】
求解方程a0+a1x+a2x2+···+anxn=0。
注意:①数据保证所有根均为小于等于20的正整数。
②数据保证方程最高次项的系数为1。
③重根也要输出。
如方程1-2x+x2=0应该输出1 1。
如方程-2+5x-4x2+x3=0应该输出1 1 2。
【输入格式】
第一行一个数表示这是一个n次方程。
第二行共n+1个数,第i个数ai表示xi-1前的系数。
【输出格式】
一共n个数,从小到大依次输出方程的n个解。
【输入样例1】
2
1 -2 1
【输出样例1】
1 1
【输入样例2】
3
-2 5 -4 1
【输出样例2】
1 1 2
【数据规模】
对于30%的数据,n=2。
对于另外20%的数据,保证方程没有重根。
对于100%的数据,n<=7,ai<=109。
解析
如果没有重根的情况,直接模拟即可。
而有重根的情况,模拟多项式除法即可。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <algorithm> #include <iostream> #include <cstring> #include <string> #include <cstdio> using namespace std; long long a[20],b[20],n; long long cf(int a,int m) //乘方 { long long sum=1; for(int i=1;i<=m;i++) sum*=a; return sum; } long long cal(int i) { int sum=0; for(int j=0;j<=n;j++) sum+=a[j]*cf(i,j); return sum; } int main() { cin>>n; for(int i=0;i<=n;i++) cin>>a[i]; for(int i=1;i<=20;i++) { while(cal(i)==0) { memset(b,0,sizeof(b)); cout<<i<<" "; for(int j=n;j>=0;j--) if(a[j]!=0&&a[j+1]!=0) { b[j]=a[j+1]; a[j]+=a[j+1]*i; } for(int j=n;j>=0;j--) a[j]=b[j]; } } return 0; }
T3 做梦
题目
【问题描述】
Lqa的家是n层的大楼。
Lqa的电梯可以采用以下四种方式移动:
- 回到第一层。
- 向上移动a层;
- 向上移动b层;
- 向上移动c层;
现在hjy来到了Lqa的家,现在他在Lqa家的第一层,碰巧电梯也在第一层。Hjy想知道,他可以乘坐电梯前往的楼层数。
【输入格式】
第一行一个整数n,表示摩天大楼的层数。
第二行三个正整数,分别表示题目中的a,b,c。
【输出格式】
一行一个整数,表示hjy可以到达的楼层数。
【样例输入】
15
4 7 9
【样例输出】
9
【样例解释】
可以到达的楼层有:1,5,8,9,10,12,13,14,15
【数据范围】
对于20%的数据,1≤h, x, y, z≤100;
对于40%的数据,1≤h, x, y, z≤105;
对于100%的数据,1≤h≤1018,1≤x, y, z≤105。
解析
原题啊——跳楼机。
令f(i)表示仅通过操作2和操作3能达到的 mod x=i的最小楼层。
于是得出状态转移方程
f(i+y)=f(i)+y;
f(i+z)=f(i)+z。
能达到 mod x=i+y的最小楼层,即在能达到 mod x=i的最小楼层上再执行一遍操作2。
再来看一遍最短路的求法。
f(y)=f(x)+edge(i)。(y为子节点,x为父节点,edge为权值)
对比一下上面的状态转移方程,是不是很像?
于是让(i+y)与(i+z)成为点,让y,z成为权值,即可求出f(i)。
ans+=(h-f[i])/x+1;
由于f(i)是在不使用操作1的情况下,所以h和f(i)之间的差值由操作1来完成。
而每用一次操作1,就可以到达一个新楼层,所以答案就要累加上进行操作1的次数。
即(h-f[i])/x+1(因为除法是向下取整,所以答案得+1)。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <queue> using namespace std; const int N=1e5+3; const int INF=0x3f3f3f3f; long long h,x,y,z; long long f[N],ans; bool vis[N]; int tot,ver[N*2],Next[N*2],edge[N*2],head[N]; void add(int x,int y,int z) { ver[++tot]=y; Next[tot]=head[x]; head[x]=tot; edge[tot]=z; } void spfa() { memset(f,INF,sizeof(f)); memset(vis,0,sizeof(vis)); queue<int> qwq; qwq.push(1); vis[1]=1; f[1]=1; while(!qwq.empty()) { int x=qwq.front();qwq.pop(); vis[x]=0; for(int i=head[x];i;i=Next[i]) { int y=ver[i]; if(f[y]>f[x]+edge[i]) { f[y]=f[x]+edge[i]; if(!vis[y]) { qwq.push(y); vis[y]=1; } } } } } int main() { cin>>h>>x>>y>>z; if(x==1 || y==1 || z==1){cout<<h;return 0;} //特判 for(int i=0;i<x;i++) { //关键点 add(i,(i+y)%x,y); add(i,(i+z)%x,z); } spfa(); for(int i=0;i<x;i++) if(f[i]<=h) ans+=(h-f[i])/x+1; //记得+1 cout<<ans; return 0; }
-------------------------------------------
In solitude,where we are least alone.
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!