题目名称 | “与” | 小象涂色 | 行动!行动! |
输入文件 | 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\n",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\n",ans); return 0; }
小象涂色
(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\n",ans); } return 0; }
行动!行动!
(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\n",ans); return 0; }
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:\n",++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\n",r,sum[r],cnt[x]); } } } }
conclusion
/* 今天很蛋疼... T1想了半天正解 还是考虑不全wa了一个 然而同桌写的暴力A了 ....这数据 T2概率dp直接暴力 T3分层图 考虑不全没分配好节点编号wa了一个 这算幸运了 只有一个这样的数据 要是出题人丧心病狂的话可以卡成零蛋... T2还是学到了东西 优化的思想很好 因为每个都一样 所以直接去掉一维 瞬间优化掉一个n 其他的嘛 记得对拍 T1可以把错误拍出来的 然而并没写 */