• NOIP 2011 提高组 Day2 校模拟 7.11


    数论只会GCD 模拟只会猜题意 贪心只能过样例!!!!!

    上午身体不适,基本上是强行趴在那写题。也不知道思路在哪个状态,看到T1第一想法居然连暴力都不是了。第一想法,居然是打表2333

    T1: 计算系数

    为什么我脑子里第一反应是打表…

    是的这是我用画图打的草稿(还有一部分打到草稿纸上了)

    然后我就写出来以下的天秀打表

    //    if(a==b&&b==1){
    //        if(k<=10){
    //            switch(k){
    //                case 0:{
    //                    cout<<0;
    //                    break;
    //                }
    //                case 1:{
    //                    cout<<0;
    //                    break;
    //                }
    //                case 2:{
    //                    if(n==0||m==0){
    //                        //2+0
    //                        cout<<1;
    //                    }
    //                    else if(n==1){
    //                        //1+1
    //                        cout<<2;
    //                    }
    //                    else{
    //                        cout<<0;
    //                    }
    //                    break;
    //                }
    //                case 3:{
    //                    if(n==0||m==0){
    //                        cout<<1;// 3+0
    //                    }
    //                    else if(n==2||m==2){
    //                        //2+1
    //                        cout<<3;
    //                    }
    //                    else{
    //                        cout<<0;
    //                    }
    //                    break;
    //                }
    //                case 4:{
    //                    if(n==3||m==3){
    //                        //3+1
    //                        cout<<4;
    //                    }
    //                    else if(n==2){
    //                        cout<<6;
    //                        //2+2
    //                    }
    //                    else if(n==0||m==0){
    //                        cout<<1;//4+0
    //                    }
    //                    else{
    //                        cout<<0;
    //                    }
    //                    break;
    //                }
    //                case 5:{
    //                    if(n==4||m==4){//4+1
    //                        cout<<5;
    //                    }
    //                    else if(m==2||n==2){
    //                        //3+2
    //                        cout<<10;
    //                    }
    //                    else if(m==0||n==0){
    //                        //5+0
    //                        cout<<1;
    //                    }
    //                    else{
    //                        cout<<0;
    //                    }
    //                    break;
    //                }    
    //                case 6:{
    //                    if(n==5||m==5){
    //                        cout<<6;//5+1
    //                    }
    //                    else if(m==0||n==0){
    //                        //6+0
    //                        cout<<1;
    //                    }
    //                    else if(m==2||n==2){//4+2
    //                        cout<<15;
    //                    }
    //                    else if(m==3){//3+3
    //                        cout<<20;
    //                    }
    //                    else{
    //                        cout<<0;
    //                    }
    //                    break;
    //                }
    //                case 7:{
    //                    if(n==6||m==6){
    //                        cout<<7;//6+1
    //                    }
    //                    else if(n==0||m==0){
    //                        cout<<1;
    //                        //7+0
    //                    }
    //                    else if(m==2||n==2){//5+2
    //                        cout<<21;
    //                    }
    //                    else if(m==3||n==3){//4+3
    //                        cout<<35;
    //                    } 
    //                    else{
    //                        cout<<0;
    //                    }
    //                    break;
    //                }
    //                case 8:{
    //                    
    //                    break;
    //                }
    //                case 9:{
    //                    
    //                    break;
    //                }
    //                case 10:{
    //                    
    //                    break;
    //                }            
    //            }
    //        }
    //        else{
    //            
    //        }
    //    }

    打到8的时候,终于打通了我的脑回路。打表找规律…这行为是真滴流氓。

    果然跟这个题目差不多,factor,类似于因子嘛(别挖我的十五级英语!!!),然后就发觉这东西是和前一项有联系的(而且还是相加的关系!)就是说,你的这个因子总是与上一个数的因子相关联。我就…痴痴地写出了以下正解…

    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long a,b,k,n,m;
    long long A[2000][2000];
    long long ans;
    const int Mogic=10007;
    int power(int a,int b){
        int ans=1;
        for(;b;b>>=1){
            if(b&1){
                ans=(long long)ans*a%Mogic; 
            }
            a=(long long)a*a%Mogic;
        }
        //cout<<"返回值为"<<ans<<endl; 
        return ans;
    }
    int main(){
        freopen("factor.in","r",stdin);
        freopen("factor.out","w",stdout);
        cin>>a>>b>>k>>n>>m;
        A[2][2]=1;A[2][0]=1;
        A[2][1]=2;
        for(int j=3;j<=k;j++){
            A[j][0]=1;
            A[j][j]=1;
            A[j][j-1]=j;
            A[j][1]=j;        
        }
        //对于每个数来说
        //他的 i分子与 k-i是相同的
        for(int x=4;x<=k;x++){
            for(int i=2;i<=k/2;i++){
             A[x][i]=A[x-1][i]+A[x-1][x-i];
             A[x][i]%=Mogic;
             A[x][x-i]=A[x][i];
            }
        }
        if(a==b&&b==1){
            cout<<A[k][n]%Mogic;
        }
        else{
            //cout<<"调用二号"<<endl;
            A[k][n]%=Mogic;
            a%=Mogic;
            b%=Mogic;
            long long dele;
            dele=power(a,n)*power(b,m);
            dele%=Mogic;
            //cout<<"dele为 "<<dele<<endl; 
            //cout<<"A k n "<<A[k][n]<<endl;
            ans=A[k][n]*dele;
            ans%=Mogic;
            cout<<ans;
        }
    }

    记着开LongLong!

    T2: 聪明的质监员

    这个质检员的形容词是聪明?

    一股腐败气息(哼)

     

    当时拿到之后脑子还是懵兮兮的,直接跟着题走去模拟了。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    const int MAXN=999999;
    int n,m,s;
    int w[MAXN];
    int V[MAXN];
    struct Factory{
        int a;
        int b;
    }Zone[MAXN];
    int ans;
    int res;
    bool Good[MAXN];
    int main(){
        //freopen("qc.in","r",stdin);
        //freopen("qc.out","w",stdout); 
        res=9999999;
        int maxx=0;
        int maxx_forzone=0;
        int minxx_forzone=900;
        cin>>n>>m>>s;
        for(int i=1;i<=n;i++){
            cin>>w[i]>>V[i];
            maxx=max(maxx,w[i]);
        }    
        int x,y;
        for(int i=1;i<=m;i++){
            cin>>x>>y;
            Zone[i].a=x;
            Zone[i].b=y;
            maxx_forzone=max(maxx_forzone,y);
            minxx_forzone=min(minxx_forzone,x);
        }
        for(int W=1;W<=maxx;W++){
            //这题估计用二分 
            //二分这个W,找到一个会产生正数差和负数差的平衡点
            //只要这个W一大,那么相应的ans值就会减小。也就是说,
            //当二分出差值一正一副的时候,对比两边的差值,得出最终答案。 
            ans=0; 
            for(int i=minxx_forzone;i<=maxx_forzone;i++){
                if(w[i]>=W){
                    Good[i]=true;
                }
                else{
                    Good[i]=false;
                }
            }
            for(int i=1;i<=m;i++){
                int tot=0;
                int val=0;
                for(int j=Zone[i].a;j<=Zone[i].b;j++){
                    if(Good[i]){
                        tot++;
                        val+=V[j];
                    }
                }
                ans+=tot*val;
    //            if(s-ans<0&&abs(s-ans)>res){
    //                break;
    //            }
                int index=abs(s-ans);
                res=min(res,index);
            }
            //cout<<"选择了 "<<W<<" 所产生的区间和为 "<<ans<<endl; 
        }
        cout<<res;
    }

    最有趣的是写着写着忽然就醒悟“哦!这是道二分题!!”

    然后看了一眼表“我去我第一题是模拟了多久…还剩十分钟…算了把这题打完拉倒了,不管二分的事了”

    喜爆零~!(好像是有个题目意思理解错了吗?)

    正解其实也就是二分+前缀和了。没办法T1玩的太嗨,T2有思路了也没用。

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include <stdlib.h>
    using namespace std;
    const int MAXN=2000010;
    int n,m;
    long long ans;
    long long S;
    long long MAX_forR;
    long long MIN_forL;
    long long w[MAXN];
    long long v[MAXN];
    struct section{
        int l;
        int r;
    }Zone[MAXN];
    long long Y,sum;
    long long FrontSum_n[MAXN];//你瞧,英语十级的气息 
    long long FrontSum_v[MAXN];
    bool check(int W){
        Y=0;sum=0;
        memset(FrontSum_n,0,sizeof(FrontSum_n));
        memset(FrontSum_v,0,sizeof(FrontSum_v));
        for(int i=1;i<=n;i++){
            if(w[i]>=W){
                FrontSum_n[i]=FrontSum_n[i-1]+1;
                FrontSum_v[i]=FrontSum_v[i-1]+v[i];    
            }
            else{
                FrontSum_n[i]=FrontSum_n[i-1];
                FrontSum_v[i]=FrontSum_v[i-1];    
            }
        }
        for(int i=1;i<=m;i++){
            Y+=(FrontSum_n[Zone[i].r]-FrontSum_n[Zone[i].l-1])*(FrontSum_v[Zone[i].r]-FrontSum_v[Zone[i].l-1]);
        }
        sum=llabs(Y-S);
        if(Y>S){
            return true;
        }
        else{
            return false;
        }
        
    }
    int main(){
        cin>>n>>m>>S;
        MIN_forL=999999999;
        ans=999999999999999;
        for(int i=1;i<=n;i++){
            cin>>w[i]>>v[i];
            MAX_forR=max(MAX_forR,w[i]);
            MIN_forL=min(MIN_forL,w[i]);
        }
        for(int i=1;i<=m;i++){
            cin>>Zone[i].l;
            cin>>Zone[i].r;
        }
        int left=MIN_forL-1;
        int right=MAX_forR+2;
        int mid;
        while(left<=right){
            mid=(left+right)/2;
            if(check(mid)){
                left=mid+1;
            } 
            else{
                right=mid-1;
            } 
            if(sum<ans){
                ans=sum;
            }
        }
        cout<<ans;
    } 

    (话说long long设定个最大值是真的麻烦…那个9写少了居然能炸一半的数据…)

    T3: 观光公交

    考场的时候没看,毕竟时间没了。

    下来之后看了看题,感觉上来说…有点像以前做过的一个缆车的题…但又不一样。

    这里有一个逻辑上的点,就是如果你开了氮气加速但到站了仍然需要等待最后一个来的人,那这波氮气就开的挺亏的。

    公交车氮气加速,你这怕是速度与激情,牛逼!

    代码来自LuoGu题解,看懂了但是真的不想再重新写一遍了…

    /*last[ i ] : 最后一个人到达i站点的时间。
    sum[ i ] : 到i站点的总人数。
    enter[ i ] : 公交车到i站点的最少时间。
    g[ i ] : 每个站点所能影响到的最远站点,即要求的影响。*/
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    //完全get,但精神受到了昨天175行重构代码结果有Bug没法Debug的重创
    //今天!决定!不!重!构!啦! 
    #define N 30001
    
    using namespace std;
    int n,m,k;
    int dis[N],last[N],g[N],enter[N];
    int ans,sum[N],maxx = -1;
    
    struct node{
        int time,start,end;
    }a[N];
    
    inline void bus(int x){
        while(x){
            --x;
            g[n] = g[n - 1] = n;
            int tar;
            maxx = -1;
            for(int i = n - 2;i >= 1;-- i){
                if(enter[i + 1] <= last[i + 1])//下一个点如果等待 
                    g[i] = i + 1;//最多影响到下一个
                else //不等待 
                    g[i] = g[i + 1];//继续减少后面的时间 
            }
            for(int i = 1;i < n;++ i){//for边数 
                int tmp = sum[g[i]] - sum[i];//最多影响的人数 
                if(tmp > maxx && dis[i] > 0){
                    maxx = tmp;
                    tar = i;//标记最优情况减的点 
                }
            }
            ans -= maxx;//更新ans 
            dis[tar] --;//减掉dis  
            for(int i = 2;i <= n;++ i){
                enter[i] = max(enter[i - 1],last[i - 1]) + dis[i - 1];//重新更新enter 
            }
        }
        return;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);// 
        for(int i = 1;i < n;++ i)
            scanf("%d",&dis[i]);//
        for(int i = 1;i <= m;++ i)
            scanf("%d%d%d",&a[i].time,&a[i].start,&a[i].end);
        for(int i = 1;i <= m;++ i){
            last[a[i].start] = max(last[a[i].start],a[i].time);//最后一个人到a[i].start站点的时间 和到这个点的时间取max 
            sum[a[i].end] ++;
        }
        enter[1] = last[1];
        for(int i = 1;i <= n;++ i)
            sum[i] += sum[i - 1];//到i站点的总人数 前缀和处理 
    
        for(int i = 2;i <= n;++ i)
            enter[i] = max(enter[i - 1],last[i - 1]) + dis[i - 1];//公车到i站点的最少时间 和最后到的时间取max 
        for(int i = 1;i <= m;++ i)
            ans += enter[a[i].end] - a[i].time;//处理出不加加速器的answer,后面就可以直接减啦~
        bus(k);
        printf("%d",ans);
        return 0;
    }//
  • 相关阅读:
    学习Python第五天
    学习Python第三天
    Mongodb
    JMS links
    笔记整理
    a* products
    String
    business knowledge
    [Java coding] leetcode notes
    [Java Basics3] XML, Unit testing
  • 原文地址:https://www.cnblogs.com/Uninstalllingyi/p/11172138.html
Copyright © 2020-2023  润新知