与
给你一个长度为(n)的序列(A),请你求出一对(A_i,A_j(1 <= i < j <= n))使(A_i)“与”(A_j)最大。
Ps:“与”表示位运算and,在c++中表示为&。
==很容易就能想到正解啊...
由与运算定义可知当对应的二进制位两个都为1时才=1
然后就贪心(?)从最高位开始找有没有两个数(and)运算时该位为1 这样出来的答案一定是最优的
题解==:
这道题主要是对二进制性质的一些应用,有体现“正难则反”的思想。
20分的暴力是很简单的枚举。然后对于另外80分,我们考虑:“与”是要求同一位均是1,结果才为1。而对于2进制,越高位有1,数字越大。所以我们可以考虑将所给数列的数字看成二进制,从二进制最高位向下枚举,若有大于等于两个数“这一位上为1”,那么最终结果的这一位肯定是1,于是我们就可以将所有“这一位上为1”的数保留下来,剩下的数舍弃;而若有少于两个数“这一位上为1”,则这一位上一定为0。
#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
const int N=3e5+50,M=1e6+50,inf=0x3f3f3f3f;
int n,ans=0,mx=0,a[N],b[N][50],base[50];
bool use[N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int main(){
freopen("and.in","r",stdin);
freopen("and.out","w",stdout);
base[0]=1;for(int i=1;i<=30;++i) base[i]=base[i-1]<<1;
rd(n);
for(int i=1;i<=n;++i){
rd(a[i]);
for(int j=0;j<=30&&base[j]<=a[i];++j)
if(base[j]&a[i]) b[i][j]=1,mx=Max(mx,j);
}
/* if(n<=5000){
for(int i=1;i<=n;++i)
for(int j=i+1,x;j<=n;++j)
if((x=a[i]&a[j])>ans) ans=x;
return printf("%d",ans);
}*/
for(int i=mx;i>=0;--i){
int cnt=0;
for(int j=1;j<=n;++j)
if(!use[j]&&b[j][i]) ++cnt;
if(cnt>=2){
for(int j=1;j<=n;++j)
if(!b[j][i]) use[j]=1;//一定不选它
ans+=base[i];
}
}
printf("%d",ans);
return 0;
}
小象涂色
小象喜欢为箱子涂色。小象现在有(c)种颜色,编号为(0sim c-1);还有n个箱子,编号为(1sim n),最开始每个箱子的颜色为(1)。小象涂色时喜欢遵循灵感:它将箱子按编号排成一排,每次涂色时,它随机选择([L,R])这个区间里的一些箱子(不选看做选0个),为之涂上随机一种颜色。若一个颜色为a的箱子被涂上b色,那么这个箱子的颜色会变成((a*b)mod c)。请问在(k)次涂色后,所有箱子颜色的编号和期望为多少?
开始按着40分的方程在那搞了一个小时! 怎么都过不了样例
最后终于醒悟QAQ
题解==:
一道有关期望的dp。首先可知每个操作中,一个物品会被染色的概率为1/2,用某种颜色染色的概率为(1/c)。
40分的方程是用f[i][j][k]表示第i个物品在j次操作次数后颜色变为k的概率,时间复杂度大概是(O(T*N*K*c^2))
60分要考虑到所有物品具有相似性,即n个物品本质是相同的,所以不用枚举物品(f[i][j])表示一个物品操作i次颜色变为j的概率。满足:
(f[i+1][j]+=f[i][j]*(1/2) f[i+1][(j*b)%c]+=f[i][j]*[(1/2)*(1/c)])
初始值(f[0][1]=1),答案就是(∑f[i][j]*j (i表示该箱子的操作次数,0 <= j<c))。复杂度(O(T*K*c^2))
#include<bits/stdc++.h>
using namespace std;
const int N=50+5,M=100+5,inf=0x3f3f3f3f;
int n,m,K,cnt[N];
double f[N][M],sum[N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int main(){
freopen("elephant.in","r",stdin);
freopen("elephant.out","w",stdout);
int T;rd(T);
while(T--){
memset(cnt,0,sizeof(cnt));
memset(f,0,sizeof(f));
memset(sum,0,sizeof(sum));
rd(n),rd(m),rd(K);
for(int i=1,l,r;i<=K;i++){
rd(l),rd(r);
for(int j=l;j<=r;j++) cnt[j]++;
}
f[0][1]=1;
for(int k=0;k<=K;++k)
for(int i=0;i<m;++i){
f[k+1][i]+=(double)f[k][i]/2;
for(int j=0;j<m;++j)
f[k+1][i*j%m]+=f[k][i]/2/m;
}
for(int i=0;i<=K;++i)
for(int j=0;j<m;++j) sum[i]+=f[i][j]*j;
double ans=0.0;
for(int i=1;i<=n;i++) ans+=sum[cnt[i]];
printf("%.9lf
",ans);
}
}
行动!行动!
大CX国的大兵Jack接到一项任务:敌方占领了n座城市(编号0~n-1),有些城市之间有双向道路相连。Jack需要空降在一个城市S,并徒步沿那些道路移动到T城市。虽然Jack每从一个城市到另一个城市都会受伤流血,但大CX国毕竟有着“过硬”的军事实力,它不仅已经算出Jack在每条道路上会损失的血量,还给Jack提供了k个“简易急救包”,一个包可以让Jack在一条路上的流血量为0。Jack想知道自己最少会流多少血,不过他毕竟是无脑的大兵,需要你的帮助。
70昏 超时
#include
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=10000+50,M=50000+50,inf=0x3f3f3f3f;
int n,m,k,s,t;
template void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<1];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
struct node{int id,bag;};
int dis[N][20];
dequeq;
void spfa(){
while(!q.empty()) q.pop_front();
memset(dis,inf,sizeof(dis));
for(int i=0;i<=k;++i) dis[s][i]=0;
q.push_back((node){s,0});
while(!q.empty()){
node nw=q.front();q.pop_front();
int u=nw.id,us=nw.bag;
for(int i=head[u],v,w;i;i=e[i].nxt){
v=e[i].v,w=e[i].w;
if(dis[v][us]>dis[u][us]+w){
dis[v][us]=dis[u][us]+w;
node vv=(node){v,us};
if(!q.empty()){
node fr=q.front();
if(dis[fr.id][fr.bag]>=dis[v][us]) q.push_front(vv);
else q.push_back(vv);
}
else q.push_back(vv);
}
if(us+1<=k&&dis[v][us+1]>=dis[u][us]){
dis[v][us+1]=dis[u][us];
node vv=(node){v,us+1};
if(!q.empty()){
node fr=q.front();
if(dis[fr.id][fr.bag]>=dis[v][us+1]) q.push_front(vv);
else q.push_back(vv);
}
else q.push_back(vv);
}
}
}
}
int main(){
freopen("move.in","r",stdin);
freopen("move.out","w",stdout);
rd(n),rd(m),rd(k),rd(s),rd(t);
for(int i=1,u,v,w;i< = m;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
spfa();
int ans=inf;
for(int i=0;i<=k;++i)
ans=Min(ans,dis[t][i]);
printf("%d",ans);
return 0;
}
==因为这个if(us+1<=k&&dis[v][us+1]>=dis[u][us])
弄成>=
然而改了之后又超空间...
后面写了dij
#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
typedef pair<int,int>pii;
const int N=10000+50,M=50000+50,inf=0x3f3f3f3f;
int n,m,k,s,t;
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<1];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
int dis[N][13];
bool vis[N][13];
struct node{
int id,bg,dis;
bool operator <(const node&A)const{return dis>A.dis;}
};
priority_queue<node> q;
void spfa(){
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
for(int i=0;i<=k;++i) dis[s][i]=0;
q.push(node{s,0,0});
while(!q.empty()){
node nw=q.top();q.pop();
int u=nw.id,us=nw.bg;
if(vis[u][us]) continue;
vis[u][us]=1;
for(int i=head[u],v,w;i;i=e[i].nxt){
v=e[i].v,w=e[i].w;
if(dis[v][us]>dis[u][us]+w){
dis[v][us]=dis[u][us]+w;
q.push(node{v,us,dis[v][us]});
}
if(us+1<=k&&dis[v][us+1]>dis[u][us]){
dis[v][us+1]=dis[u][us];
q.push(node{v,us+1,dis[v][us+1]});
}
}
}
}
int main(){
freopen("move.in","r",stdin);
freopen("move.out","w",stdout);
rd(n),rd(m),rd(k),rd(s),rd(t);
for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
spfa();
int ans=inf;
for(int i=0;i<=k;++i)
ans=Min(ans,dis[t][i]);
printf("%d",ans);
return 0;
}
summary
- 不能因为题做过就很飘
- lxy太辣鸡 还要加油QAQ