zoukankan      html  css  js  c++  java
  • 膜你赛 2021.10.18

    2021.10.18 膜你赛


    T1

    Description

    由于小 X 是一个奆老,所以他看不起普通商店里卖的电子秤,他决定自己做一个。
    他的称重工具是一架由金子制成的天平, 这架天平的精度非常高, 可以达到纳克的标准,
    1g=10 9 ng,小 X 会把物品放在天平的右侧,然后在天平的左侧和右侧都放上一些砝码,直至
    天平平衡。该天平的砝码是用钻石制成的,每个砝码的质量依次为 1ng、3ng、9ng、27ng、
    81ng……,每个砝码的质量都是 3 的幂次(如 3 的 6 次幂表示为 3^6=729),且各不相同。
    由于小 X 是一个奆老,他有对各个物品未卜先知的能力,他会告诉你他的物品的质量,
    希望你给他一个方案,使得天平的两侧平衡。

    Solution

    对于给出的 W,进行三进制拆分,如果这一位是 1,砝码加在左边,如果当前是 2,砝码加在右边,并进位。

    Code

    /*
    * @Author: smyslenny
    * @Date:    2021.10.
    * @Title:
    * @Main idea:
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <iomanip>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    #include <map>
    
    #define int long long
    #define INF 0x3f3f3f3f
    #define orz cout<<"LKP AK IOI
    "
    #define MAX(a,b) (a)>(b)?(a):(b)
    #define MIN(a,b) (a)>(b)?(a):(b)
    
    using namespace std;
    const int mod=1e9+7;
    const int M=1e3+5;
    int n;
    int read()
    {
        int x=0,y=1;
        char c=getchar();
        while(c<'0' || c>'9') {if(c=='-') y=0;c=getchar();}
        while(c>='0' && c<='9') { x=x*10+(c^48);c=getchar();}
        return y?x:-x;
    }
    int tre[M],num,fg;
    int ans_l[M],ans_r[M],js_l,js_r=1;
    bool check(int x)
    {
    	return x==n;
    }
    namespace substack1{
    	void dfs(int pos)
    	{
    		if(fg) return;
    		if(check(num)) 
    		{
    			fg=1;
    			for(int i=1;i<=js_l;i++) printf("%lld ",ans_l[i]);
    			printf("
    %lld ",n);
    			for(int i=1;i<=js_r;i++) printf("%lld ",ans_r[i]); 
    			printf("
    ");
    			return;
    		}
    		if(pos>10) return;
    		ans_l[++js_l]=tre[pos];
    		num+=tre[pos];
    		dfs(pos+1);
    		num-=tre[pos]*2;
    		js_l--;
    		ans_r[++js_r]=tre[pos];
    		dfs(pos+1);
    		num+=tre[pos];
    		js_r--;
    		dfs(pos+1);
    	}	
    	void main()
    	{
    		dfs(0);
    	}
    }
    namespace substack2{
    	void dfs(int pos)
    	{
    		if(fg) return;
    		if(check(num)) 
    		{
    			fg=1;
    			for(int i=1;i<=js_l;i++) printf("%lld ",ans_l[i]);
    			printf("
    %lld ",n);
    			for(int i=1;i<=js_r;i++) printf("%lld ",ans_r[i]); 
    			printf("
    ");
    			return;
    		}
    		if(pos>10) return;
    		ans_l[++js_l]=tre[pos];
    		num+=tre[pos];
    		dfs(pos+1);
    		num-=tre[pos]*2;
    		js_l--;
    		ans_r[++js_r]=tre[pos];
    		dfs(pos+1);
    		num+=tre[pos];
    		js_r--;
    		dfs(pos+1);
    	}	
    	void main()
    	{
    		dfs(0);
    	}
    }
    namespace substack3{
    	int tri[M],cnt,sz[M],zs[M],m,mm;
    	void main()
    	{
    		int W=n,s=1;
    		while(W)
    		{
    			tri[++cnt]=W%3;
    			W/=3;
    		}
    		for(int i=1;i<=cnt+1;i++)
    		{
    			if(tri[i]==1)
    			{
    				if(sz[mm]==s)
    					sz[mm]=s*3,zs[++m]=s;
    				else sz[++mm]=s;
    			}
    			if(tri[i]==2)
    			{
    				if(sz[mm]==s)
    					sz[mm]=s*3;
    				else zs[++m]=s,sz[++mm]=s*3;
    			}
    			s*=3;
    		}
    //		printf("%d ",sz[1]);
    		for(int i=1;i<=mm;i++) printf("%lld ",sz[i]);
    		printf("
    %lld ",n);
    		for(int i=1;i<=m;i++) printf("%lld ",zs[i]);
    	}
    }
    signed main()
    {
    //	freopen("entertain.in","r",stdin);
    //	freopen("entertain.out","w",stdout);
    	n=read();
    //	tre[0]=1;
    //	for(int i=1;i<=50;i++) tre[i]=tre[i-1]*3;
    //	js_l=0,js_r=0;
    //	if(n<=10000) substack1::main();
    //	else substack2::main(); 
    	substack3::main();
    	return 0;
    }
    		 
    
    

    T2

    Description

    小 S 和小 Z 十分喜欢看网络写手“2 5 ”的小说,但由于需要付费才能阅读,而小 S 和小
    Z 的零花钱有非常少,他们只能找小 X 靠黑科技侵入给网站,把小说给他们。
    然而小 X 又非常的爱慕虚荣,他要小 S 和小 Z 到自己家里来取小说。
    小 S、小 Z 和小 X 都居住在扬中市,扬中市共有 n 个小区,m 条主干道(假设每条主干
    道都是双行线)。小 S 家住在 1 号小区,小 X 家住在 n 号小区。小 S 每经过一条主干道需要
    耗费 z 点体力,但由于小 S 的人脉非常广,每当他到达一个小区,他都会和好友攀谈直到体
    力回满。
    由于小 Z 也希望能看到小说,所以他答应帮助小 S k 次,这 k 次小 S 经过主干道不需要
    耗费体力。
    由于小 S 生性懒惰,他希望耗费最少的体力到达小 X 家,请问他最少耗费多少体力?
    注意:如果小 S 到小 X 家可以一路上都由小 Z 背着,那么体力上限为 0;
    如果小 S 到不了小 X 家,小 S 会很伤心,体力上限为-1;

    Solution

    二分一个最大值,最短路check 一下。
    由于数据不是很强,也可以跑分层图。

    Code

    /*
    * @Author: smyslenny
    * @Date:    2021.10.
    * @Title:
    * @Main idea:
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <iomanip>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    #include <map>
    
    #define ll long long
    #define INF 0x3f3f3f3f
    #define orz cout<<"LKP AK IOI
    "
    #define MAX(a,b) (a)>(b)?(a):(b)
    #define MIN(a,b) (a)>(b)?(a):(b)
    
    using namespace std;
    const int mod=1e9+7;
    const int M=1e4+5;
    int n,m,k,Ans=-1;
    int read()
    {
        int x=0,y=1;
        char c=getchar();
        while(c<'0' || c>'9') {if(c=='-') y=0;c=getchar();}
        while(c>='0' && c<='9') { x=x*10+(c^48);c=getchar();}
        return y?x:-x;
    }
    struct ed{
    	int u,v,w,net;
    }edge[M<<1];
    int head[M],num;
    void addedge(int u,int v,int w)
    {
    	edge[++num].u=u;
    	edge[num].v=v;
    	edge[num].w=w;
    	edge[num].net=head[u];
    	head[u]=num;
    }
    
    struct node{
    	int u,dis;
    	bool operator < (const node &a) const {
    		return dis>a.dis;
    	}
    };
    priority_queue<node> q;
    int dis[M],vis[M];
    int check(int mid)
    {
    	memset(dis,INF,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	dis[1]=0; 
    	q.push(node{1,dis[1]});
    	while(!q.empty())
    	{
    		node x=q.top();
    		q.pop();
    		int u=x.u;
    		vis[u]=1;
    		for(int i=head[u];i;i=edge[i].net)
    		{
    			int v=edge[i].v,w=edge[i].w,dist=dis[u];
    			if(vis[v]) continue;
    			if(w>=mid) dist++;
    			if(dis[v]>dist)
    			{
    				dis[v]=dist;
    				q.push(node{v,dis[v]});
    			}
    		}
    	}
    	return dis[n]>=k+1;
    }
    
    int main()
    {
    	freopen("novel.in","r",stdin);
    	freopen("novel.out","w",stdout);
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=m;i++)
    	{
    		int u=read(),v=read(),w=read();
    		addedge(u,v,w);
    		addedge(v,u,w);
    	}
    	int l=0,r=1e6+100;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(check(mid))
    			l=mid+1,Ans=mid;
    		else r=mid-1;
    	}
    	if(Ans>1e6) printf("-1
    ");
    	else if(r<0) printf("0
    ");
    	else printf("%d
    ",Ans);
    	return 0;
    }
    

    T3

    Description

    他准备给两位奆老中的一个人绿叶配红花,另一个人红叶配绿花。
    由于绿叶配红花大家说顺口了, 所以小 X 家楼下的花店里就有出售, 但红叶配绿花是小
    X 口味独特的体现,花店里当然是不会有的,小 X 只能自行拼凑。
    他家种了一棵枫树,现在有的枫叶是红色的,有的枫叶是黄色的,小 X 只要采摘红色的
    枫叶。每片枫叶有一个年轻程度,他希望他采摘的枫叶的年轻程度总和越小越好。
    这棵枫树有 n 个节点(从 0 开始编号),m 片叶子。他希望采摘到恰好 k 片红色叶子的
    经过每个节点的年轻程度总和最小的生成树。
    注意:保证数据有解。

    Solution

    wqs二分的板子题,当时我竟然没想到!

    Code

    /*
    * @Author: smyslenny
    * @Date:    2021.10.
    * @Title:
    * @Main idea:
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <iomanip>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    #include <map>
    
    #define ll long long
    #define INF 0x3f3f3f3f
    #define orz cout<<"LKP AK IOI
    "
    #define MAX(a,b) (a)>(b)?(a):(b)
    #define MIN(a,b) (a)>(b)?(a):(b)
    
    using namespace std;
    const int mod=1e9+7;
    const int M=5e4+5;
    int n,m,k,js,Ans;
    int read()
    {
        int x=0,y=1;
        char c=getchar();
        while(c<'0' || c>'9') {if(c=='-') y=0;c=getchar();}
        while(c>='0' && c<='9') { x=x*10+(c^48);c=getchar();}
        return y?x:-x;
    }
    
    int du[M],f[M],tot,cnt;
    int find(int x)
    {
    	if(f[x]==x) return x;
    	return f[x]=find(f[x]);
    }
    struct ed{
    	int u,v,w,col;
    }edge[M<<1],e[M<<1];
    
    bool cmp(ed a,ed b)
    {
    	if(a.w==b.w) return a.col<b.col;
    	return a.w<b.w;
    }
    
    bool check(int mid)
    {
    	tot=cnt=0;
    	for(int i=1;i<=n;i++) f[i]=i;
    	for(int i=1;i<=m;i++)
    	{
    		e[i]=edge[i];
    		if(edge[i].col==0) e[i].w+=mid;
    	}
    	sort(e+1,e+1+m,cmp);
    	for(int i=1;i<=m;i++)
    	{
    		int fa=find(e[i].u),fb=find(e[i].v);
    		if(fa!=fb)
    		{
    			f[fa]=fb;
    			tot+=e[i].w;
    			if(!e[i].col) cnt++;
    		}
    	}
    	return cnt>=k;
    }
    // 
    int main()
    {
    //	freopen("leaf.in","r",stdin);
    //	freopen("leaf.out","w",stdout); 
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=m;i++)
    		edge[i].u=read()+1,edge[i].v=read()+1,edge[i].w=read(),edge[i].col=read();
    	int l=-105,r=105;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(check(mid))
    			l=mid+1,Ans=tot-k*mid;//减去我们二分的附加值 
    		else r=mid-1;
    	}
    	printf("%d
    ",Ans);
    	return 0;
    }
    
    本欲起身离红尘,奈何影子落人间。
  • 相关阅读:
    python 对xls写入信息
    Python 字符串前面加u,r,b,f的含义
    inner join 与 left join 之间的区别
    时间戳转换成日期展示的方法 且 搜索范围
    Python与C/C++相互调用(python2 调c++那个试了ok)
    爆库记录(X-Forwarded-For注入漏洞实战 记录)
    笔记
    墨者学习安全测试的网站(看起来很不错的样子 有空看看)
    sqlmap开源 测试sql注入的工具 各种参考链接
    菜鸟浅谈——web安全测试(这篇不错有空看看)
  • 原文地址:https://www.cnblogs.com/jcgf/p/15427258.html
Copyright © 2011-2022 走看看