您的位置:首页 > 其它

2017.4.22NOIP2017模拟考试总结

2017-04-22 16:35 330 查看
 本次的三道题难度偏低,第一题是一个非常裸的二分答案,第二题就是排一个序,然后相乘,主要是用到了二进制乘法,第三题就是一道裸地差分约束,没有什么问题。结果考试只有第三题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<
4000
;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
<<endl;
}


后记:

这次考试题目简单,就是一些细节需要注意,平时把每个算法的细节理解透,考试的时候能得心应手
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: