Codeforces 1408F Two Different 二进制拆分,分治法

文章目录


题目链接

题意

定义 f ( a , b ) f(a,b) f(a,b)为定义域为正整数对,值域为正整数的任意函数,并且自变量相同的时候保证函数值相同.
给一个长度为 n n n的序列 a a a,一开始 a [ i ] = i a[i]=i a[i]=i.每次可以选择序列中的两个数
x i , y i ∈ [ 1 , n ] xi,yi \in [1,n] xi,yi[1,n],使 a [ x i ] = a [ y i ] = f ( a [ x i ] , a [ y i ] ) a[xi]=a[yi]=f(a[xi],a[yi]) a[xi]=a[yi]=f(a[xi],a[yi]), 你需要构造一个操作顺序使得不论 f f f函数如何定义,最终操作的结果都能使序列中不相同数的种数小于或者等于2.

题解

首先思考有没有可能出现 f ( x , y ) = f ( a , b ) f(x,y)=f(a,b) f(x,y)=f(a,b)的情况(x,y和a,b两个数对不完全相同).
这是不可能的,因为每当出现一个新 l , r l,r l,r数对的时候我们都可以令它的函数值为当前数列中最大的数+1,这样总有一种函数构造使得只要 a , b a,b a,b数对不相同,函数值就不相同,因此这种方法失效了.
那么不妨考虑四个数的情况.
先操作 1 , 2 1,2 1,2,再操作 3 , 4 3,4 3,4.然后操作 1 , 3 1,3 1,3 2 , 4 2,4 2,4. ∵ a 1 = a 2 , a 3 = a 4 , ∴ f ( a 1 , a 3 ) = f ( a 2 , a 4 ) \because a1=a2,a3=a4,\therefore f(a1,a3)=f(a2,a4) a1=a2,a3=a4,f(a1,a3)=f(a2,a4),此时四个数完全一样.
同理,只要 2 n 2^n 2n个数,我们就可以把它变得完全相同.
那么多出来的怎么办呢?
很简单啊,取 2 i 2^i 2i使 2 i ≤ n 2^i\leq n 2in 2 i 2^i 2i最大,先用上述操作把前 2 i 2^i 2i变相同,再用同样的方法把后 2 i 2^i 2i个数字也变成相同的,此时数列中显然只有两种不同数字.
由于顺序枚举比较难,不妨采用递归分治法.
我一开始完全不知道方法,就随机几次操作了一下,没想到出来了,我才仔细思考其中的原理.

#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);
}

谢谢大家.

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/108893316
今日推荐