zoukankan      html  css  js  c++  java
  • 2017-9-12 NOIP模拟赛[hkd]

    NOIP 2017 全假模拟冲刺


    T1 Spfa


    题目描述
    B 国在耗资百亿元之后终于研究出了新式武器——连环阵(Zenith Protected
    Linked Hybrid Zone)。传说中,连环阵是一种永不停滞的自发性智能武器。但
    经过 A 国间谍的侦察发现,连环阵其实是由 M 个编号为 1,2,…,M 的独立武器
    组成的。最初,1 号武器发挥着攻击作用,其他武器都处在无敌自卫状态。以后,一
    旦第 i(1<=i< M)号武器被消灭,1 秒种以后第 i+1 号武器就自动从无敌自卫状
    态变成攻击状态。当第 M 号武器被消灭以后,这个造价昂贵的连环阵就被摧毁了。
    为了彻底打击 B 国科学家,A 国军事部长打算用最廉价的武器——炸弹来消灭连环
    阵。经过长时间的精密探测,A 国科学家们掌握了连环阵中 M 个武器的平面坐标,然
    后确定了 n 个炸弹的平面坐标并且安放了炸弹。每个炸弹持续爆炸时间为 5 分钟。
    在引爆时间内,每枚炸弹都可以在瞬间消灭离它平面距离不超过 k 的、处在攻击状态
    的 B 国武器。和连环阵类似,最初 a1 号炸弹持续引爆 5 分钟时间,然后 a2 号炸
    弹持续引爆 5 分钟时间,接着 a3 号炸弹引爆……以此类推,直到连环阵被摧毁。
    显然,不同的序列 a1、a2、a3...消灭连环阵的效果也不同。好的序列可以在仅使
    用较少炸弹的情况下就将连环阵摧毁;坏的序列可能在使用完所有炸弹后仍无法将连
    环阵摧毁。现在,请你决定一个最优序列 a1、a2、a3…使得在第 ax 号炸弹引爆的
    时间内连环阵被摧毁。这里的 x 应当尽量小。
    输入格式:
    第一行包含两个整数:n 和 m
    输出格式:
    一行包含一个整数 x,表示斐波那契数列的第 n 项和第 m 项的最大公约数对
    1000000007 取模后的结果。
    样例输入:
    4 7
    样例输出:
    1
    于 对于 20%据 的数据 1<=n,m<=2000000
    于 对于 50%据 的数据 1<=n,m<=200000000
    于 对于 100%据 的数据 1<=n,m<=10^18

    /*
        (f(n),f(m))=f((n,m))
        再用矩阵乘法优化计算
    */
    #include<cstdio>
    #include<iostream>
    #define Mod 1000000007
    #define Max 2
    using namespace std;
    struct Martix_Data {
        long long data[Max][Max];
        void Prepare(){
            data[0][0]=1;
            data[0][1]=1;
            data[1][0]=1;
            data[1][1]=0;
        }
        Martix_Data operator * (const Martix_Data now) const {
            Martix_Data res;
            for (int i=0;i<Max;i++)
                for (int j=0;j<Max;j++) {
                    res.data[i][j]=0;
                    for (int k=0;k<Max;k++)
                        res.data[i][j]=(res.data[i][j]+data[i][k]*now.data[k][j])%Mod;
                }
            return res;
        }
    };
    Martix_Data operator ^ (Martix_Data &now, long long P) {
        Martix_Data res;
        res.Prepare ();
        res.data[1][0]=0;
            while(P){
                if (P&1)
                    res=res*now;
                now=now*now;
                P>>=1;
            }
        return res;
    }
    long long N;
    long long gcd(long long x,long long y){
        if(y==0)return x;
        return gcd(y,x%y);
    }
    int main () {
        //scanf("%lld",&N);
        freopen("spfa.in","r",stdin);
        freopen("spfa.out","w",stdout);
        long long n,m;
        cin>>n>>m;
        N=gcd(n,m);
        if(N==1||N==2){
            printf("1");
            return 0;
        }
        Martix_Data Answer;
        Answer.Prepare();
        Answer=Answer^(N-2);
        cout<<Answer.data[0][0];
        return 0;
    }
    100分

    T2 走 楼梯缩小版


    每一个阳光明媚的午后,xxy 总是欢快地在楼梯上跳来跳去,两具 hkd 的尸
    体躺在楼梯下面,却影响不了 xxy 继续跳楼梯的想法。每次想到这个画面,xxy 总
    是激动地双手猛拍轮椅,仿佛要站起来一样。
    由于 xxy 拍轮椅太过用力,所以 xxy 的轮椅被拍烂了,xxy 掉到地上摔成了 n
    个小的 xxy,xxy 们惊喜的发现楼梯刚好有 n 个台阶,但是 xxy 们在每个 xxy 楼梯的高
    度上产生了纠纷,xxy 们的智慧是不一定相同的,她们认为自己上方的台阶上的 xxy 不
    能不如自己聪明,但由于 xxy 摔倒的时候是没有规律的,所以小的 xxy 们初始的位置
    是不一定满足他们的要求的,所以每个 xxy 可以送给前方与她相邻的 xxy1 点的智慧而
    交换位置。
    现在给出 xxy 们初始的智慧,求能否通过交换来满足 xxy 们的要求。
    如果满足,请输出“Happy”,否则输出“Sad”,并输出捶死几个小 xxy 可以
    满足 xxy 们的要求。
    输入格式:
    一个整数 T,表示有 T 组数据。(T<=10)。
    第一行包含一个整数:n(1<=n<=2*10^5)
    第二行包括 n 个整数,第 i 个数表示第 i 个 xxy 的智慧。
    后一个 xxy排在前一个 xxy 的前面
    输出格式:
    一行包含一字符串 “Happy”,或“Sad”。
    如果第一行输出“Sad”,第二行一个整数,表示捶死几个小 xxy 可以满足 xxy 们的要
    求。
    样例输入:
    1
    2
    9 8
    样例输出:
    Sad
    1
    样例解释
    不管怎么交换总是满足不了 xxy 们要求,而只要
    随便捶死一个 xxy 就可以满足要求。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int n,T;
    int main(){
        freopen("small.in","r",stdin);
        freopen("small.out","w",stdout);
        scanf("%d",&T);
        while(T--){
            vector<int>q;
            scanf("%d",&n);
            int x;
            for(int i=1;i<=n;i++){
                scanf("%d",&x);x+=i;
                q.push_back(x);
            }
            sort(q.begin(),q.end());
            q.erase(unique(q.begin(),q.end()),q.end());
            int len=q.size();
            if(len==n){
                printf("Happy
    ");
                continue;
            }
            printf("Sad
    ");
            printf("%d
    ",n-len);
        }
    }
    65分
    /*
        不难证明a[i]+i是一个常数
        如果a[i]+i==a[j]+j那么这就是一组不合法解
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int n,T;
    int qread(){
        int i=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
        return i;
    }
    int main(){
        freopen("small.in","r",stdin);
        freopen("small.out","w",stdout);
        scanf("%d",&T);
        while(T--){
            vector<int>q;
            n=qread();
            int x;
            for(int i=1;i<=n;i++){
                x=qread();x+=i;
                q.push_back(x);
            }
            sort(q.begin(),q.end());
            q.erase(unique(q.begin(),q.end()),q.end());
            int len=q.size();
            if(len==n){
                printf("Happy
    ");
                continue;
            }
            printf("Sad
    ");
            printf("%d
    ",n-len);
        }
    }
    100分

    T3 huaji.jpg


    滑稽们在愉快地做游戏,xxy 身为在跳楼梯这一极限运动领域已经登峰造极的人来
    说,跳楼梯已经满足不了她了,她想对滑稽们搞些大新闻。
    她用比香港记者跑得还快的速度来到了滑稽树下,对着滑稽们大喊:“整个城乡结
    合部敢对我用这个表情的人不超过三个。”滑稽们感到很气恼,但良好的素养让他们决定
    不和 xxy 这个粗鲁的人一般计较,xxy 接着喊;“南方好还是北方好?”。滑稽们再也忍
    不住了,决定用跳舞的方式来计算出给她来几分钟的禁言套餐。
    滑稽们有三种跳舞的方式,分别是 5,五和⑤。每次 5 可以储存一部分的能量,为
    五做准备,储存的能量为当前滑稽们的个数,如果每次储存之前滑稽们就有能量,就把之
    前的能量清空。每次五可以产生新的滑稽,每储存一点能量就可以产生一个新的滑稽,但
    产生新的滑稽不需要消耗能量。每次⑤可以把两个滑稽融合成一个滑稽,并结出一个滑稽
    果。
    滑稽们其实心中已经决定了要给 xxy 一个 n 分钟的禁言套餐,跳舞只是走走形式,
    所以滑稽们不想消耗太多的体力,每种舞都会消耗一点的体力,所以,单纯的滑稽们把这
    个问题交给了你,请你在 1.5s 内给出答案,否则滑稽们就会和你在滑稽树前做游♂戏。
    一个滑稽可以禁言一分钟。
    输入格式:
    第一行包含一个整数:n(1<=n<=10^6)
    输出格式:
    第一行包括一个整数:ans,表示最小的体力。
    样例输入:
    233
    样例输出:
    17
    于 对于 100%据 的数据 n<=10^6

    /*
        三种操作:复制,粘贴,退格
        我们知道只复制不粘贴是没有任何意义的,所以复制粘贴看作是一步
        在1000000范围内,退格的使用次数不会超过40次,复制粘贴只需要建图跑一遍spfa,求出dis[n]
    */
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=1000010;
    const int p[46]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199};
    int n,pre[N],dis[N],q[N+10],head,tail;
    bool vis[N];
    #define v (u*p[i])
    #define vv (u-1)
    void spfa(){
        memset(dis,127,sizeof(dis));
        dis[1]=0;q[tail=1]=1;head=0;
        while(head!=tail){
            int u=q[++head];vis[u]=0;
            if(head==N)head=0;
            for (int i=0;i<46;++i){
                if(v>n+20) break;
                if(v<n+20&&dis[v]>dis[u]+p[i]){
                    dis[v]=dis[u]+p[i];
                    if(!vis[v]){
                        vis[v]=1;q[++tail]=v;
                        if(tail==N)tail=0;
                    }
                }
            }
            if(u>0&&dis[vv]>dis[u]+1){
                dis[vv]=dis[u]+1;
                if(!vis[vv]){
                    vis[vv]=1;q[++tail]=vv;
                    if(tail==N)tail=0;
                }
            }
        }
    }
    int main()
    {
        freopen("huaji.in","r",stdin);
        freopen("huaji.out","w",stdout);
        scanf("%d",&n);
        spfa();printf("%d
    ",dis[n]);
        return 0;
    }
    (0)100分 spfa
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,dp[1000045],lit;
    int main()
    {
        freopen("huaji.in","r",stdin);
        freopen("huaji.out","w",stdout);
        cin>>n;
        memset(dp,127/3,sizeof(dp)),dp[1]=0;
        for(int i=1,v,base;i<=n+40;++i)
        {
            base=dp[i];
            for(v=1;true;++v)
                if(dp[i+v]+v<=base) base=dp[i+v]+v;
                else break;
            dp[i]=base,++base;
            for(v=1;i+v*i<=n+40;++v)
                dp[i+v*i]=min(dp[i+v*i],base+v);
        }
        cout<<dp[n];
        return 0;
    }
    100分 线段树(myj)
  • 相关阅读:
    列行oracle行转列、列转行
    内存销毁Android中Context
    继承指针《深度探索C++对象模型》侯捷译——笔记(一),读后感,附带【插图】
    函数环境lua5.1.4中实现自定义require的loader函数
    修改文件vim 插件:perlsupport的修改和使用
    查询文件[置顶] Android 仿 WP7 布局
    权限用户Exchange 2010 出现用户无权限发邮件,产生的原因是部分用户权限被覆盖或者丢失!
    参数过滤mongodb过滤查询键值
    效果信息[gdc13]《刺客信条3》渲染技术
    破解服务器Android防破解
  • 原文地址:https://www.cnblogs.com/thmyl/p/7510087.html
Copyright © 2011-2022 走看看