题意:
让你构造一个有向图,使得这张图从1到n的路径长度集合在L~R中间,切L~R中间所有值都正好只有一条从1到n的长度相同的路径与之对应。
让你用不超过32个点构造这张图
题解:
一如既往没有想法的构造题,但是我看到一个比较优秀的解法:
首先对于32这个数字我们能想到的就是二进制去构造
像这样去就可以构造出
0
,
2
x
−
1
0,2^x-1
0,2x−1的数,
然后只需要1向所有点连边就可以构造出
L
,
L
+
2
x
−
1
L,L+2^x-1
L,L+2x−1
很明显R不会总是
L
+
2
x
−
1
L+2^x-1
L+2x−1,但是我们拥有的不仅仅是第x个数,第i的贡献区间是
2
i
2^i
2i,那么我们只需要在R-L这个数上的第i位,且第i位是1,(表示它缺少这个长度的区间去构成R-L),将前i位都变成0的时候的值+1,设它为v+1,连到n上即可。表示我们拥有的值域加上了
L
+
v
+
1
,
L
+
v
+
2
i
L+v+1,L+v+2^i
L+v+1,L+v+2i。就像这样:
#include<bits/stdc++.h>
using namespace std;
const int N=35;
struct node{
int x,y,v;
};
vector<node>vec;
int main()
{
int l,r;
scanf("%d%d",&l,&r);
printf("YES\n");
for(int i=2;i<=22;i++)vec.push_back({1,i,l});
for(int i=2,v=1;i<=20;i++,v*=2)
for(int j=i+1;j<=21;j++)
vec.push_back({i,j,v});
r-=l;
for(int i=2,v=0;i<=21;i++,v++)
if(r&(1<<v))
r^=(1<<v),vec.push_back({i,22,r+1});
printf("22 %d\n",vec.size());
for(node i:vec)
printf("%d %d %d\n",i.x,i.y,i.v);
return 0;
}