【2019.9.3】

给你一个长度为\(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\)种颜色,编号为\(0\sim c-1\);还有n个箱子,编号为\(1\sim 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\n",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
posted @ 2019-09-03 15:32  委屈的咸鱼鱼鱼鱼  阅读(121)  评论(0编辑  收藏  举报