本次的三道題難度偏低,第一題是一個非常裸的二分答案,第二題就是排一個序,然後相乘,主要是用到了二進制乘法,第三題就是一道裸地差分約束,沒有什麼問題。結果考試只有第三題A了,第一題和第二題都WA了,歸根到底還是自己對於基礎的模板不熟練,如二分答案的判斷等。
T1:二分答案加模擬判斷
題意:一共有n堆果子,m個袋子,每堆果子有一個體積,求最小的袋子體積v可裝完所有果子,注意袋子可以不裝滿
#include<cstdio>
#include<cstdlib>
#include<iomanip>
#include<iostream>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<set>
#include<queue>
using namespace std;
long long n,m,sum,maxx=-1,a[100005];
//---------------------
inline long long Readint()
{
long long i=0,f=1;
char ch;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())
i=(i<<1)+(i<<3)+ch-'0';
return i*f;
}
//---------------------
inline bool check(long long x)
{
long long temp=x,tot=1;
for(long long i=1;i<=n;i++)
{
if(a[i]<=temp)
{
temp=temp-a[i];
continue; //考試的時候沒有打,果然還是太NAIVE,一個點都沒過
}
if(a[i]>temp&&a[i]<=x)
{
tot++;
temp=x-a[i];
continue;
}
if(a[i]>x) return false;
}
if(tot<=m) return true;
else return false;
}
int main()
{
freopen("fruit.in","r",stdin);
freopen("fruit.out","w",stdout);
n=Readint(),m=Readint();
for(long long i=1;i<=n;i++){
a[i]=Readint();
sum+=a[i];
maxx=max(maxx,a[i]);
}
long long l=maxx,r=sum,mid;//顯然下界是a[i]的最大值,上界是總和
while(l<(r-1))
{
mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid;
}
cout<<r<<endl;
return 0;
}
T2:題意有n個零件,每個零件有一個加工時間和懲罰,懲罰是從第一個開始計算,一個零件的懲罰等於它的懲罰乘上等待的時間,注意第一個零件無懲罰貪心。
題解:有點隱蔽的貪心,可以用數形結合的方法發現以斜率爲關鍵字排序,也可以直接推的式子。
按照t/s升序排序然後計算,比較大小的時候由於浮點精度誤差,double的精度有可能不夠,這個時候用交叉相乘。對於x1/y1 與 x2/y2大小比較,應該: x1*y2 與 x2*y1比較!
另外,排序還可以這樣排
bool cmp(const node&a,const node&b)//用斜率來排序
{
return a.t*b.fine<a.fine*b.t;
}
//---------------------
long long mul(long long a,long long b)//避免高精度,用二進制優化
{
long long r;
for(r=0;b;a=(a<<1)%m,b>>=1)
if(b&1) r=(r+a)%m;
return r;
}
int main()
{
freopen("process.in","r",stdin);
freopen("process.out","w",stdout);
n=Readint(),scanf("\n"),m=Readint(),scanf("\n");
for(long long i=1;i<=n;i++)
work[i].t=Readint(),work[i].fine=Readint();
sort(work+1,work+1+n,cmp);
for(long long i=2;i<=n;i++)
{
sumt=(sumt+work[i-1].t)%m;
ans=(ans+mul(sumt,(work[i].fine%m)))%m;
}
cout<<ans<<endl;
return 0;
}
T3:裸的差分約束,就不贅述了
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,tot,first[500050],dis[500010],q[500010];
bool in[500010];
//---------------------
inline int Readint()
{
int i=0,f=1;
char ch;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())
i=(i<<1)+(i<<3)+ch-'0';
return i*f;
}
//---------------------
struct node
{
int to,next,w;
}edge[4000010];
//---------------------
void create(int x,int y,int z)
{
tot++;
edge[tot].to=y;
edge[tot].w=z;
edge[tot].next=first[x];
first[x]=tot;
}
//---------------------
inline void spfa()
{
int head=0,tail=1;
dis[0]=0;
while(head!=tail)
{
head++;
if(head==500001)head=1;
in[q[head]]=false;
for(int u=first[q[head]];u;u=edge[u].next)
{
if(dis[edge[u].to]<dis[q[head]]+edge[u].w)
{
dis[edge[u].to]=dis[q[head]]+edge[u].w;
if(!in[edge[u].to])
{
in[edge[u].to]=true;
tail++;
if(tail==500001)tail=1;
q[tail]=edge[u].to;
}
}
}
}
}
//---------------------
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=Readint(),m=Readint();
int x;
for(int i=1;i<=n;i++){
x=Readint();
create(i,i-1,-x);
}
for(int i=1;i<=n;i++) create(i-1,i,0);
for(int i=1;i<=m;i++){
int l,r,c;
l=Readint(),r=Readint(),c=Readint();
create(l-1,r,c);
}
memset(dis,-63,sizeof(dis));
spfa();
cout<<dis[n]<<endl;
}
後記:
這次考試題目簡單,就是一些細節需要注意,平時把每個算法的細節理解透,考試的時候能得心應手