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

 

原文地址:https://www.cnblogs.com/yanlifneg/p/5868943.html