2017.4.22NOIP2017模拟考试总结

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

后记:
这次考试题目简单,就是一些细节需要注意,平时把每个算法的细节理解透,考试的时候能得心应手

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值