[hdu 4896]14多校J题 Minimal Spanning Tree 打表

来源:互联网 发布:php imagepng 编辑:程序博客网 时间:2024/06/01 09:58
Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 77    Accepted Submission(s): 16


Problem Description
Given a connected, undirected, weight graph G, your task is to select a subset of edges so that after deleting all the other edges, the graph G is still connected. If there are multiple ways to do this, you should choose the way that minimize the sum of the weight of these selected edges.

Please note that the graph G might be very large. we'll give you two numbers: N, and seed, N is number of nodes in graph G, the following psuedo-code shows how to to generate graph G.



Here ⊕ represents bitwise xor (exclusive-or).
 

Input
Input contains several test cases, please process till EOF.
For each test case, the only line contains two numbers: N and seed.(1 ≤ N ≤ 10000000, 1 ≤ seed ≤ 2333332)
 

Output
For each test case output one number, the minimal sum of weight of the edges you selected.
 

Sample Input
6 28772 178863 22452
 

Sample Output
21578102596371352144
 

Source
2014 Multi-University Training Contest 3
 
题目大意
以题目所给的伪代码生成一个图,求最小生成树的长度
解题思路
N太大,暴力可能RE+MLE+TLE……
注意到x的取值,907与2333333互质,一定会有循环节出现=。=
愉快的打表,发现循环节只有54……

根据生成出来的图,第6~n个点会有5条边
由于边的取值可能为前面1-5个点中某个点的XOR
猜测规律循环节为60*54……

打表开测……
最后发现答案的循环节还是54……
注意到1 55 109的值还是不一样的,那就先暴力打出前108个值,剩余的按照循环节处理

code:
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath> #include <string>#include <map>#define eps 1e-9#define LL long long#define mod 2333333using namespace std;map <int , int> ma;int pos[100];int clo,p,ed;struct node{int x,y,w;}a[250000];int f[500];LL te[200];int cmp(node a,node b){return (a.w<b.w);}int getf(int x){if (x==f[x]) return x;else return (f[x]=getf(f[x]));}int unite(int x,int y){// printf("%d %d\n",x,y);if (getf(x)!=getf(y)) f[getf(x)]=getf(y);}LL kru(){LL ans=0;for (int i=1;i<=ed;i++)if (getf(a[i].x)!=getf(a[i].y)) {ans+=a[i].w;unite(a[i].x,a[i].y);}return ans;}int main(){LL n,seed;while (~scanf("%I64d%I64d",&n,&seed)){ma.clear();int cur=seed;int t=0;while (ma[cur]==0){t++;pos[t]=cur;pos[0]=cur;ma[cur]=1;cur=cur*907%mod;}for (int k=1;k<=108;k++){for (int i=1;i<=k;i++)f[i]=i;clo=ed=0;for (int i=1;i<=k;i++){clo++;clo%=54;p=pos[clo];for (int j=max(1,i-5);j<i;j++){clo++;clo%=54;ed++;a[ed].x=i;a[ed].y=j;a[ed].w=pos[clo]^p;}}sort(a+1,a+1+ed,cmp);te[k]=kru();//暴力前108个结果}// for (int i=1;i<=100;i++)// printf("%I64d ",te[i]);if (n<=108) printf("%I64d\n",te[n]);else printf("%I64d\n",te[54+n%54]+(n/54-1)*(te[108]-te[54]));}return 0;}


2 0
原创粉丝点击