zoukankan      html  css  js  c++  java
  • 9.13noip模拟试题

     

    题目名称

    “与”

    小象涂色

    行动!行动!

    输入文件

    and.in

    elephant.in

    move.in

    输出文件

    and.out

    elephant.in

    move.in

    时间限制

    1s

    1s

    1s

    空间限制

    64MB

    128MB

    128MB 

    “与”

    (and.pas/.c/.cpp)

    时间限制:1s;空间限制64MB

    题目描述:

    给你一个长度为n的序列A,请你求出一对Ai,Aj(1<=i<j<=n)使Ai“与”Aj最大。

    Ps:“与”表示位运算and,在c++中表示为&。

    输入描述:

    第一行为n。接下来n行,一行一个数字表示Ai。

    输出描述:

    输出最大的Ai“与”Aj的结果。

    样例输入:

    3

    8

    10

    2

    样例输出:

    8

    样例解释:

    8 and 10 = 8

    8 and 2 = 0

    10 and 2 = 2

    数据范围:

    20%的数据保证n<=5000

    100%的数据保证 n<=3*10^5,0<=Ai<=10^9

    据说暴力就能过...

    /*
    n*n暴力很好想
    如果按照二进制位数给这些数分类的话
    不是很极端的数据的话每一类的数不会很多
    从高位开始处理 找出第一个一定是答案
    然后乱搞一下把极端数据特判掉就好了 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 300010
    using namespace std;
    int n,a[maxn],c[33][maxn],r[maxn],tot,ans;
    int init(){
        int x=0;char s=getchar();
        while(s<'0'||s>'9')
        s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int cmp(int a,int b){
        return a>b;
    }
    int main()
    {
        freopen("and.in","r",stdin);
        freopen("and.out","w",stdout);
        n=init();
        for(int i=1;i<=n;i++)
            a[i]=init();
        sort(a+1,a+1+n,cmp);
        if(a[2]==a[1]){
            printf("%d
    ",a[1]);
            return 0;
        }
        for(int i=1;i<=n;i++)
            if(a[i]==a[i-1])ans=max(ans,a[i]);
        for(int i=1;i<=n;i++){
            int x=a[i],k=0;
            while(x)k++,x>>=1;
            c[k][++c[k][0]]=a[i];
        }
        for(int i=32;i>=1;i--){
            if(!c[i][0])continue;
            if(c[i][1]<=ans)break;
            int mxx=0;
            for(int j=1;j<=c[i][0];j++)
                for(int k=1;k<=c[i][0];k++){
                    if(j!=k)mxx=max(mxx,c[i][j]&c[i][k]);
                    if(mxx>c[i][k]||ans>c[i][k])break;
                }
                    
            for(int j=1;j<=c[i][0];j++)
                for(int k=1;k<=tot;k++)
                    mxx=max(mxx,c[i][j]&r[k]);
            ans=max(ans,mxx);
            if(ans)break;    
            for(int j=1;j<=c[i][0];j++)
                r[++tot]=c[i][j];
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

     

      

    小象涂色

    (elephant.pas/.c/.cpp)

    时间限制:1s,空间限制128MB

    题目描述:

    小象喜欢为箱子涂色。小象现在有c种颜色,编号为0~c-1;还有n个箱子,编号为1~n,最开始每个箱子的颜色为1。小象涂色时喜欢遵循灵感:它将箱子按编号排成一排,每次涂色时,它随机选择[L,R]这个区间里的一些箱子(不选看做选0个),为之涂上随机一种颜色。若一个颜色为a的箱子被涂上b色,那么这个箱子的颜色会变成(a*b)mod c。请问在k次涂色后,所有箱子颜色的编号和期望为多少?

    输入描述:

    第一行为T,表示有T组测试数据。

    对于每组数据,第一行为三个整数n,c,k。

    接下来k行,每行两个整数Li,Ri,表示第i个操作的L和R。

    输出描述:

    对于每组测试数据,输出所有箱子颜色编号和的期望值,结果保留9位小数。

    样例输入:

    3

    3 2 2

    2 2

    1 3

    1 3 1

    1 1

    5 2 2

    3 4

    2 4

    样例输出:

    2.062500000

    1.000000000

    3.875000000

    数据范围:

    40%的数据1 <= T <= 5,1 <= n, k <= 15,2 <= c <= 20

    100%的数据满足1 <= T <= 10,1 <= n, k <= 50,2 <= c <= 100,1 <= Li <= Ri <= n

    /*
    dp题 没想到....
    f[i][j][k]第i次涂色之后 j位置是k颜色的概率
    这会超时 其实考虑到所有物品具有相似性,即n个物品本质是相同的,
    所以不用枚举物品 
    f[i][j]表示一个物品操作i次颜色变为j的概率 
    先搞出每个物品染色的次数 然后dp
    最后统计答案 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 110
    using namespace std;
    int T,n,c,K,l,r,cnt[maxn],mxx;
    double f[maxn][maxn],ans;
    void Clear(){
        memset(cnt,0,sizeof(cnt));
        memset(f,0,sizeof(f));
        f[0][1]=1;ans=0;mxx=0;
    }
    int main()
    {
        freopen("elephant.in","r",stdin);
        freopen("elephant.out","w",stdout);
        scanf("%d",&T);
        while(T--){
            scanf("%d%d%d",&n,&c,&K);
            Clear();
            for(int i=1;i<=K;i++){
                scanf("%d%d",&l,&r);
                for(int j=l;j<=r;j++){
                    cnt[j]++;mxx=max(mxx,cnt[j]);
                }
            }
            for(int i=0;i<mxx;i++){
                for(int j=0;j<c;j++){
                    f[i+1][j]+=f[i][j]/2;
                    for(int k=0;k<c;k++)
                        f[i+1][(j*k)%c]+=f[i][j]/(2*c);
                }    
            }
            for(int i=1;i<=n;i++)
                for(int j=0;j<c;j++)
                    ans+=f[cnt[i]][j]*j;
            printf("%.9f
    ",ans);
        }
        return 0;
    }
    View Code

     

     

     

     

     

    行动!行动!

    (move.pas/.c/.cpp)

    时间限制:1s;空间限制:128MB

    题目描述:

    大CX国的大兵Jack接到一项任务:敌方占领了n座城市(编号0~n-1),有些城市之间有双向道路相连。Jack需要空降在一个城市S,并徒步沿那些道路移动到T城市。虽然Jack每从一个城市到另一个城市都会受伤流血,但大CX国毕竟有着“过硬”的军事实力,它不仅已经算出Jack在每条道路上会损失的血量,还给Jack提供了k个“简易急救包”,一个包可以让Jack在一条路上的流血量为0。Jack想知道自己最少会流多少血,不过他毕竟是无脑的大兵,需要你的帮助。

    输入描述:

    第一行有三个整数n,m,k,分别表示城市数,道路数和急救包个数。

    第二行有两个整数,S,T。分别表示Jack空降到的城市编号和最终要到的城市。

    接下来有m行,每行三个整数a,b,c,表示城市a与城市b之间有一条双向道路。

    输出描述:

    Jack最少要流的血量。

    样例输入:

    5 6 1

    0 3

    3 4 5

    0 1 5

    0 2 100

    1 2 5

    2 4 5

    2 4 3

    样例输出:

    8

    数据范围:

    对于30%的数据,2<=n<=50,1<=m<=300,k=0;

    对于50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;

    对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.

    /*
    分层图 没啥可说的
    因为k<=10所以拓展点的时候直接x+10+y了
    但其实k==10的话这样拓展会重复...
    幸好只有一个点...
    谨慎谨慎..
    还有就是 这题这样做的话卡SPFA
    要用dij 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define pa pair<int,int>
    #define mk make_pair
    #define maxn 200100
    #define maxm 2000100
    using namespace std;
    int n,m,k,num,head[maxn],f[maxn],dis[maxn],S,T,l,r,ans=0x3f3f3f3f;
    struct node{
        int v,t,pre;
    }e[maxm*2];
    priority_queue<pa,vector<pa>,greater<pa> >q;
    int init(){
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int Cal(int x,int y){
        return 11*x+y;
    }
    void Add(int from,int to,int dis){
        for(int i=head[from];i;i=e[i].pre)
            if(e[i].v==to){
                e[i].t=min(e[i].t,dis);
                return;
            }
        num++;e[num].v=to;
        e[num].t=dis;
        e[num].pre=head[from];
        head[from]=num;
    }
    void Dij(int s){
        memset(dis,127/3,sizeof(dis));
        dis[s]=0;q.push(mk(0,s));
        while(!q.empty()){
            int u=q.top().second;
            q.pop();
            if(f[u])continue;f[u]=1;
            for(int i=head[u];i;i=e[i].pre){
                int v=e[i].v;
                if(dis[v]>dis[u]+e[i].t){
                    dis[v]=dis[u]+e[i].t;
                    q.push(mk(dis[v],v));
                }
            }
        }
    }
    int main()
    {
        freopen("move.in","r",stdin);
        freopen("move.out","w",stdout);
        n=init();m=init();k=init();
        S=init();T=init();S++;T++;
        int u,v,t;
        for(int i=1;i<=m;i++){
            u=init();v=init();t=init();
            u++;v++;
            for(int j=0;j<=k;j++){
                Add(Cal(u,j),Cal(v,j),t);
                Add(Cal(v,j),Cal(u,j),t);
                if(j){
                    Add(Cal(u,j),Cal(v,j-1),0);
                    Add(Cal(v,j),Cal(u,j-1),0);
                }
            }
        }
        Dij(Cal(S,k));
        for(int i=0;i<=k;i++)
            ans=min(ans,dis[Cal(T,i)]);
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    Hzwer的陨石

    (meteorite.pas/.c/.cpp)

    时间限制:1s;空间限制:128MB

    题目描述:

    经过不懈的努力,Hzwer召唤了很多陨石。已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域。有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域的陨石全搬到了另外一些区域。

    在ndsf愉快的搬运过程中,Hzwer想知道一些陨石的信息。对于Hzwer询问的每个陨石i,你必须告诉他,在当前这个时候,i号陨石在所在区域x、x区域共有的陨石数y、以及i号陨石被搬运的次数z。

    输入描述:

    输入的第一行是一个正整数T。表示有多少组输入数据。

    接下来共有T组数据,对于每组数据,第一行包含两个整数:N和Q。

    接下来Q行,每行表示一次搬运或一次询问,格式如下:

    T A B:表示搬运,即将所有在A号球所在地区的陨石都搬到B号球所在地区去。

    Q A:悟空想知道A号陨石的x,y,z。

    输出描述:

    对于第i组数据,第一行输出“Case i:”接下来输出每一个询问操作的x,y,z,每一个询问操作的答案占一行。每组数据之间没有空行。

    样例输入:

    2

    3 3

    T 1 2

    T 3 2

    Q 2

    3 4

    T 1 2

    Q 1

    T 1 3

    Q 1

    样例输出:

    Case 1:

    2 3 0

    Case 2:

    2 2 1

    3 3 2

    数据范围:

    20%的数据保证:0≤T≤20,2<N<=100,2<Q<=100。

    100%的数据保证:0≤T≤100,2<N<=10000,2<Q<=10000。

    对于所有数据保证搬运操作中AB在N的范围内且所在区域不相同。:

    /*
    带权并查集 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 10010
    using namespace std;
    int T,n,m,fa[maxn],cnt[maxn],sum[maxn],cas;
    char c[5];
    int init(){
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    void Clear(){
        for(int i=1;i<=n;i++){
            fa[i]=i;sum[i]=1;
        }
        memset(cnt,0,sizeof(cnt));
    }
    int find(int x){
        if(x==fa[x])return x;
        int f=fa[x];
        fa[x]=find(fa[x]);
        cnt[x]+=cnt[f];
        return fa[x];
    }
    void Union(int a,int b){
        int r1=find(a);
        int r2=find(b);
        if(r1==r2)return;
        fa[r1]=r2;
        sum[r2]+=sum[r1];
        sum[r1]=0;cnt[r1]++;
    }
    int main()
    {
        freopen("meteorite.in","r",stdin);
        freopen("meteorite.out","w",stdout);
        T=init();
        while(T--){
            n=init();m=init();
            Clear();int x,y;
            printf("Case %d:
    ",++cas);
            while(m--){
                scanf("%s",c);
                if(c[0]=='T'){
                    x=init();y=init();
                    Union(x,y);
                }
                else{
                    x=init();int r=find(x);
                    printf("%d %d %d
    ",r,sum[r],cnt[x]);
                }
            }
        }
    }
    View Code

     conclusion

    /*
    今天很蛋疼...
    T1想了半天正解 还是考虑不全wa了一个
    然而同桌写的暴力A了 ....这数据
    T2概率dp直接暴力
    T3分层图 考虑不全没分配好节点编号wa了一个
    这算幸运了 只有一个这样的数据 要是出题人丧心病狂的话可以卡成零蛋...
    
    T2还是学到了东西
    优化的思想很好 因为每个都一样 所以直接去掉一维
    瞬间优化掉一个n
    其他的嘛 记得对拍 T1可以把错误拍出来的 然而并没写
    */
    View Code

     

  • 相关阅读:
    Python之路——内置函数
    Python之路——迭代器与生成器
    Python之路——函数
    Python之路——琐碎知识
    oracle 11g ocp 笔记(17)--rman高级功能
    oracle 11g ocp 笔记(16)--使用rman进行恢复
    oracle 11g ocp 笔记(15)--使用rman进行备份
    oracle 11g ocp 笔记(14)--数据库备份和恢复配置
    oracle 11g ocp 笔记(13)--子查询和集合运算符
    oracle 11g ocp 笔记(12)--sql关联
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5868943.html
Copyright © 2011-2022 走看看