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;
}

後記:
這次考試題目簡單,就是一些細節需要注意,平時把每個算法的細節理解透,考試的時候能得心應手

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章