题目链接
题意
定义
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
2i≤n且
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);
}
谢谢大家.