• [思维构造] 题解 Omkar and Duck


    [思维构造] 题解 Omkar and Duck

    题目链接

    题目大意

    构造一个 (n imes n) 的矩阵,每个元素取值范围为 ([0,10^{16}]) ,使得所有从 ((1,1)) 仅往下或往右走走到 ((n,n)) 的路径的权值两两不同(一条路径的权值定义为这条路径经过的所有元素之和)。

    (1le nle 25)

    题目分析

    思路一

    神 @Imakf 提供了一种构造方法,把向右走认为是字符“a”,向左走认为是字符“b”,把所有 ((1,1))((n,n)) 的路径写成字符串然后按照字典序排序后依次钦定权值为 (0,1,dots,{2(n-1)choose n-1}-1) ,然后按照这个钦定的权值去给每个格子赋值就行了。

    这样做为什么是对的?如果将所有路径插入 Trie 树,那么某个点 ((x,y))((n,n)) 的所有路径在 Trie 树上面是连续的,按照上面的构造方法所有路径的权值也就是连续的一段,由此不难发现这样构造就是正确的(或者说钦定的权值并不会出现冲突)。

    具体如何实现?认为左上角是 ((1,1)) 右下角是 ((n,n)) ,给每个格子 ((x,y)) 记录一个 ([L,R]) 表示 ((x,y))((n,n)) 的所有路径的权值取值范围,先钦定第 (n) 列的所有元素取值 (0) ,然后按列数从大到小,行数从大到小确定每个格子元素的取值,先认为当前格子取值为 (0) ,看从当前格子向下走和向右走的权值是否有重复,如果有的话就加大当前格子下面格子的取值。这样构造在极限数据 (n=25) 时每个元素取值是符合范围的。

    思路二

    考虑二进制拆分,使用如下构造方式:

     0  0  0  0
     1  2  4  8
     0  0  0  0
     4  8 16 32
    

    (奇数行所有元素为 (0) ,偶数行位置 ((x,y)) 的值为 (2^{x+y-3})

    这种方法相当于把某个数二进制表示下若干连续的 (1) 绑定在一起,连续的 (1) 在同一行一起经过,不连续的 (1) 在不同行经过,不难发现这样构造也不会出现重复。

    参考代码

    思路一的代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ch() getchar()
    #define pc(x) putchar(x)
    using namespace std;
    template<typename T>void read(T&x){
    	static char c;static int f;
    	for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
    	for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
    }
    template<typename T>void write(T x){
    	static char q[65];int cnt=0;
    	if(x<0)pc('-'),x=-x;
    	q[++cnt]=x%10,x/=10;
    	while(x)
    		q[++cnt]=x%10,x/=10;
    	while(cnt)pc(q[cnt--]+'0');
    }
    long long L[35][35],R[35][35],val[35][35];
    int main(){
    	int n;read(n);
    	for(int i=1;i<=n;++i){
    		val[i][n]=0;
    		L[i][n]=R[i][n]=0;
    	}
    	for(int j=n-1;j>=1;--j){
    		val[n][j]=0;
    		L[n][j]=R[n][j]=L[n][j+1];
    		for(int i=n-1;i>=1;--i){
    			val[i][j]=0;
    			if(L[i+1][j]<=R[i][j+1]){
    				long long delta=R[i][j+1]-L[i+1][j]+1;
    				L[i+1][j]+=delta,R[i+1][j]+=delta;
    				val[i+1][j]+=delta;
    			}
    			L[i][j]=L[i][j+1];R[i][j]=R[i+1][j];
    		}
    	}
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;pc(" 
    "[j==n]),++j)
    			write(val[i][j]);
    	fflush(stdout);
    	int q;read(q);
    	while(q--){
    		long long x;read(x);
    		int nx=1,ny=1;
    		while(nx<=n&&ny<=n){
    			write(nx),pc(' '),write(ny),pc('
    ');
    			if(nx<n&&L[nx+1][ny]<=x&&x<=R[nx+1][ny]){
    				x-=val[nx+1][ny];++nx;
    			}
    			else{
    				x-=val[nx][ny+1];++ny;
    			}
    		}
    		fflush(stdout);
    	}
    	return 0;
    }
    /*
    _|_|_|_|        _|_|      _|      _|   _|_|_|_|_|   _|_|_|_|_|   _|
    _|      _|    _|    _|    _|_|    _|       _|       _|           _|
    _|      _|   _|      _|   _| _|   _|       _|       _|           _|
    _|      _|   _|_|_|_|_|   _|  _|  _|       _|       _|_|_|_|_|   _|
    _|      _|   _|      _|   _|   _| _|       _|       _|           _|
    _|      _|   _|      _|   _|    _|_|       _|       _|           _|
    _|_|_|_|     _|      _|   _|      _|   _|_|_|_|_|   _|_|_|_|_|   _|_|_|_|_|
    
    _|_|_|_|_|   _|      _|   _|_|_|_|     _|      _|
        _|        _|    _|    _|      _|    _|    _|
        _|         _|  _|     _|      _|     _|  _|
        _|          _|_|      _|      _|      _|_|
        _|         _|  _|     _|      _|       _|
        _|        _|    _|    _|      _|       _|
        _|       _|      _|   _|_|_|_|         _|
    
    _|             _|_|_|     _|      _|   _|_|_|_|_|
    _|           _|      _|   _|      _|   _|
    _|           _|      _|    _|    _|    _|
    _|           _|      _|    _|    _|    _|_|_|_|_|
    _|           _|      _|     _|  _|     _|
    _|           _|      _|      _|_|      _|
    _|_|_|_|_|     _|_|_|         _|       _|_|_|_|_|
    
    _|_|_|_|_|   _|      _|   _|_|_|_|_|
        _|        _|    _|        _|
        _|         _|  _|         _|
        _|          _|_|          _|
        _|           _|           _|
        _|           _|           _|
        _|           _|           _|
    
    Created by xiaolilsq.
    */
    
    
    
  • 相关阅读:
    nginx js、css多个请求合并为一个请求(concat模块)
    Web客户端语言HTML、XHTML和XML相关知识介绍
    正则小略
    你可能不知道的5个功能强大的 HTML5 API
    你须知道的30个CSS选择器 »
    css3 media媒体查询器用法总结
    深入java虚拟机学习 -- 类的加载机制
    ElasticSearch和solr的差别
    idea 使用debugger技巧
    vue学习问题总结(一)
  • 原文地址:https://www.cnblogs.com/lsq147/p/14599072.html
Copyright © 2020-2023  润新知