• 【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)种颜色,编号为(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
  • 相关阅读:
    D1
    测试 Collectors 类中相关 API,以及 Collector 接口中 Characteristics 的枚举值
    Servlet 整合 freemarker、如何在 freemarker 中自定义标签
    webLogic javaweb 路径问题 Not allowed to load local resource
    高复用、高兼容的 ajaxForm 上传文件
    Extjs 4+ 中的 combobox 的级联
    Echarts中关于雷达图极坐标值相差过大时的图像展示问题
    java 使用poi操作Excel(2003,2007)实现数据批量导入的一般思路
    java 使用poi操作Excel表格(2003,2007)实现数据的批量导出
    Ext3.4 表格基本操作
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11453350.html
Copyright © 2020-2023  润新知