[模拟赛] MST 打表??不知所云

MST

给定一张n个点的完全图,点的编号为0~n-1,每两个点u,v间的边权和为u xor v(xor为两个数的异或),求这个图的最小生成树所有边权的异或和。

【输入格式】

  输入一行一个数n,

【输出格式】

  输出一个数表示该图的最小生成树边权异或和。

【数据规模与约定】

对于1~4的测试点:n<=1000

对于5~6的测试点:n<=7000

对于7~8的测试点:n<=10^7

对于9~10的测试点:n<=10^12

考试的时候各种胡思乱想。。。这数据怕不是要log(n)???O(1)(下面有O(1) by 羊肉汤泡煎饼)。。。异或来异或去。。老脸MengB。。。

要不,打表。。。。开始打prim的表、、、、以下是d数组(就是把它们异或起来就是答案)

what。。。

what。。。woc!震惊。。竟然长得如此之像。。。于是想求出每个数的出现次数。。。如果是偶数就相当于没有贡献,是奇数就异或一次。。。log(n)妥妥的。。。

#include<cstdio>
#include<iostream>
#define ll long long
#define R register ll
using namespace std;
ll n;
ll pow[42]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552};
ll ans;
signed main() {
    freopen("mst.in","r",stdin);
    freopen("mst.out","w",stdout);
    scanf("%lld",&n); //cout<<n<<endl;
    for(R i=1;pow[i]/2<=n;++i) {
        ans^=((((n-pow[i-1]+pow[i]-1)/pow[i])&1)?pow[i-1]:0); 
        //cout<<pow[i-1]<<pow[i]<<" "<<((n-pow[i-1]+pow[i]-1)/pow[i])<<endl;
    } printf("%lld\n",ans);
}

而旁边的 羊肉汤泡煎饼 发现了通项公式。。。太强了。。。十分接近O(1)。。。只不过说异或常数大。。。还是%%%

scanf("%lld",&n);n--;
printf("%lld",(n^(n/2)));

震恐而瑟瑟发抖。。。


好吧,打表大法好。。。

2019.04.18

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/10727218.html
MST