Codeforces 1408F Two Different 二进制拆分,分治法
文章目录
- 题意
- 题解
题目链接
题意
定义f(a,b)f(a,b)f(a,b)为定义域为正整数对,值域为正整数的任意函数,并且自变量相同的时候保证函数值相同.
给一个长度为nnn的序列aaa,一开始a[i]=ia[i]=ia[i]=i.每次可以选择序列中的两个数
xi,yi∈[1,n]xi,yi \in [1,n]xi,yi∈[1,n],使a[xi]=a[yi]=f(a[xi],a[yi])a[xi]=a[yi]=f(a[xi],a[yi])a[xi]=a[yi]=f(a[xi],a[yi]), 你需要构造一个操作顺序使得不论fff函数如何定义,最终操作的结果都能使序列中不相同数的种数小于或者等于2.
题解
首先思考有没有可能出现f(x,y)=f(a,b)f(x,y)=f(a,b)f(x,y)=f(a,b)的情况(x,y和a,b两个数对不完全相同).
这是不可能的,因为每当出现一个新l,rl,rl,r数对的时候我们都可以令它的函数值为当前数列中最大的数+1,这样总有一种函数构造使得只要a,ba,ba,b数对不相同,函数值就不相同,因此这种方法失效了.
那么不妨考虑四个数的情况.
先操作1,21,21,2,再操作3,43,43,4.然后操作1,31,31,3和2,42,42,4.∵a1=a2,a3=a4,∴f(a1,a3)=f(a2,a4)\because a1=a2,a3=a4,\therefore f(a1,a3)=f(a2,a4)∵a1=a2,a3=a4,∴f(a1,a3)=f(a2,a4),此时四个数完全一样.
同理,只要2n2^n2n个数,我们就可以把它变得完全相同.
那么多出来的怎么办呢?
很简单啊,取2i2^i2i使2i≤n2^i\leq n2i≤n且2i2^i2i最大,先用上述操作把前2i2^i2i变相同,再用同样的方法把后2i2^i2i个数字也变成相同的,此时数列中显然只有两种不同数字.
由于顺序枚举比较难,不妨采用递归分治法.
我一开始完全不知道方法,就随机几次操作了一下,没想到出来了,我才仔细思考其中的原理.
#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{typedef long long ll;
#define re0 register int
#define rel register ll
#define rec register char
#define gc getchar
//#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?-1:*p1++)
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
char buf[1<<23],*p1=buf,*p2=buf;
inline int read(){int x=0,f=1;char c=gc();for (;!isdigit(c);c=gc()) f^=c=='-';for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');return f?x:-x;}
template <typename mitsuha>
inline bool read(mitsuha &x){x=0;int f=1;char c=gc();for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';if (!~c) return 0;for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');return x=f?x:-x,1;}
template <typename mitsuha>
inline int write(mitsuha x){if (!x) return 0&pc(48);if (x<0) pc('-'),x=-x;int bit[20],i,p=0;for (;x;x/=10) bit[++p]=x%10;for (i=p;i;--i) pc(bit[i]+48);return 0;}
inline char fuhao(){char c=gc();for (;isspace(c);c=gc());return c;}
}using namespace chtholly;
using namespace std;
namespace ran{const int mod=1e9+7,k1=17,k2=53,mak=2147483647;
const int mak1=0x57b8ce1d,mak2=0x2af4c7e1;
ll sa,sb;
inline ll kasumi(ll a,ll b,bool bo=1){ll s=1;for (;b;b>>=1,a=bo?a*a%mod:a*a&mak) if (b&1) s=bo?s*a%mod:s*a&mak;return s; }
inline ll rnd(){sa=(sa*k1+k2)%mod*kasumi(sa+2,sb+2)%mod;sb=(sb*kasumi(sb+2,sa+2)%mod*k2+k1)%mod;return (sa+sb)%mod;}
inline ll rndll(){sa=((kasumi(sa^mak1,sb^mak2,0)^rnd())*k1+k2)&mak;sb=((kasumi(sb^mak1,sa^mak2,0)^rnd())*k2+k1)&mak;return sa<<30|sb;}
inline ll rnd(ll l,ll r){return l+rnd()%(r-l+1);}
inline ll rndll(ll l,ll r){return l+rndll()%(r-l+1); }
inline void init(){srand(time(0));sa=rand()^mak1,sb=rand()^mak2;rnd(),rnd(),rnd();}
}using ran::rnd;using ran::rndll;
const int yuzu=5e5;
typedef int fuko[yuzu|10];
fuko a,q1,q2;
typedef pair<int,int> pii;
vector<pii> lxy;
void dfs(int l,int r) {if (l==r) return;int mid=l+r>>1,i,j;dfs(l,mid),dfs(mid+1,r);for (i=l,j=mid+1;i<=mid;++i,++j) lxy.push_back(pii(i,j));
}
int main() {int n=read(),i,j,k=0,l;for (i=0;(1<<i)<=n;++i); --i;dfs(1,1<<i),dfs(n-(1<<i)+1,n);printf("%d\n",(int)lxy.size());for (pii x:lxy) printf("%d %d\n",x.first,x.second);
}
谢谢大家.
Codeforces 1408F Two Different 二进制拆分,分治法相关推荐
- 分治法的思想与经典题目
目录 分治法简介 分治法主定理 分治算法的时间复杂度 分治法的基本步骤 分治法的使用条件 分治法的经典题目 50. Pow(x, n) 53. 最大子序和 169. 多数元素 分治法简介 分治法,即& ...
- python分治算法_python算法实现-分治法
分治法概念将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----"分" 将最后子问题可以简单的直接求解----"治" 将所有子问 ...
- c++分治法求最大最小值实现_程序员:算法导论,分治法、归并排序,伪代码和Java实现...
分治法 我们首先先介绍分治法.分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后在合并这些子问题的解来解决原问题的解. 还是拿扑克牌举例子,假设桌上有两堆牌面朝 ...
- aes算法实现c语言_以C语言实现归并排序为例,谈谈五大常用算法之一的“分治法”...
分治算法,顾名思义就是"分而治之",即把规模较大的复杂问题拆分为若干规模较小的类似子问题,并逐个解决,最后再将各个子问题的解决结果合并,得到原始问题的结果的方法.这个技巧是很多高效 ...
- python分治算法_分治法及其python实现例子
在前面的排序算法学习中,归并排序和快速排序就是用的分治法,分治法作为三大算法之一的,有非常多的应用例子. 分治法概念 将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题-- ...
- 分治法的经典问题——大整数相乘
分治法的经典问题--大整数相乘 分治法的原理 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解.即一种分目标 ...
- [转载] 算法导论:分治法,python实现合并排序MERGE-SORT
参考链接: Python中的合并排序merge sort 1. 简单合并排序法实现 思想:两堆已排好的牌,牌面朝下,首先掀开最上面的两张,比较大小取出较小的牌,然后再掀开取出较小牌的那一堆最上面的牌和 ...
- 大整数乘法(分治法)
大整数乘法(分治法) 题目描述:设X和Y都是n位的十进制整数,计算它们的乘积X*Y. 如果按照我们日常的计算方法,应该就是将两个数逐位相乘,最后加起来得到最终的结果,时间复杂度为O(n2); 因此我们 ...
- 算法与数据结构-分治法
分治法 分治法的思想 将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治模式在每层递归时都有三个步骤: 分解(Divide):将原 ...
最新文章
- linux驱动学习笔记(2.4) scull 脚本scull_init
- 学习shell脚本之乘法口诀
- linux安装tightvnc_tightvnc安装配置,在Linux系统中进行tightvnc安装配置
- CentOS 初体验九:curl 的使用
- 外卖匹配系统_“外卖智能算法”和大学生有啥关系?来自工科生的专业分析
- 经典算法题每日演练——第九题 优先队列
- SAP CRM responsibility的维护
- bigdecimal 平均数_MapReduce实例-必须用Combine--求平均数
- Snipaste在Window运行后遇到提示计算机中丢失 api-ms-win-crt-runtime-l1-1-0.dll 错误
- ESXI主机的Management网络管理了什么?
- win10系统windows hello无法设置 windows hello设置开启教程
- 因开源协议“大打出手”,AWS 宣布创建 Elasticsearch、Kibana 分支
- 马云放弃阿里巴巴所有权?华硕裁员上百人;扎克伯格账号被黑 | 极客头条
- mysql root dengru_Mysql学习Mysql中文汉字转拼音的实现(每个汉字转换全拼)
- ios开发闹钟步骤_苹果快捷指令自动化(起床关闹钟后自动播放音乐)
- ps 填充颜色快捷键
- h5页面自定义字体_自定义app字体(原生+h5)
- github WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
- 深入理解计算机系统(v3) 第三章、程序的机器级表示(Linux)
- GDT、GDTR、LDT、LDTR的理解 [zz]
热门文章
- 计算机组成原理 - I/O(输入输出)系统
- Unity官方流化功能接入细节
- c语言数据结构常考算法,第6讲嵌入式C语言_常见数据结构及算法..docx
- DMA技术和及其SG模式
- 23种设计模式(十四)模板方法模式(阁瑞钛伦特软件-九耶实训)
- 利用Simulink、STM32CUBEMX、STM32-MAT/TARGET自动生成简单的led灯闪烁代码(保姆级教程)
- tensorboard生成的网址打不开的解决方法
- 哈佛大学公开课:计算机科学cs50 学习笔记及代码练习(第14集:栈,队列,哈希表,树)
- pycharm安装到32位操作系统
- (转)python环境搭建和pycharm的安装配置及汉化