[考试反思]0116省选模拟9:赌注

又是运气场。。。

T2有一大堆结论不是很可想。T1暴力分给了20剩下的十分麻烦。T3是个十合一。

什么神奇考试。。。

考场上看了一下前两题觉得不是很可做。

于是直接奔着提答去了,最后只剩下100分钟的时候才回来看前两题。

然后还是觉得T1数上树非常恶心于是式子都没化打暴力跑路,T2打结论啥也想不出来,只考虑了第一种情况扔上继续跑路。

于是又一次跑到了T3。

然而非常弱智,T1的根号筛欧拉函数又写挂了。

第三行i写成x了。弱智

然后T3的第7个点我居然把样例文件交上去了。。。。

而且T3的第5个点还没想到用欧拉函数求逆元

然后第8个点的类原题的做法也忘掉了

后来改题的时候线筛欧拉函数又写错了

过年回家希望有人能送我个好使点的脑子。。。

这场考试也纯粹是运气好,平时提答做的比较多所以占了点便宜。

而且刚题了还赶上没看的题基本不可做。。。

下次要注意。

T1:Surprise me

大意:给定树,求树上所有点对$(u,v)$的$dis(u,v)varphi(u)varphi(v)$的期望。$n le 200000$

还是用到那个结论:$varphi(ab)=frac{varphi(a)varphi(b) gcd(a,b)}{varphi(gcd(a,b))}$

把$gcd$提出去,反演化式子,得到$sumlimits_{p=1} f(p) sumlimits_{i=1}^{frac{n}{p}} sumlimits_{j=1}^{frac{n}{p}} dep_{ip} varphi(ip) varphi(jp) +dep_{jp} varphi(ip) varphi(jp) -2dep_{lca(ip,jp) varphi(ip) varphi(jp)}$

其中$f(p)=sumlimits_{d|p} frac{d}{varphi(d)} mu(frac{p}{d})$

对于要求的式子,前两部分可以乘法分配律求和直接处理。最后一个部分考虑树上$dp$

发现一共只涉及到了$n ln n$个点,每次只对需要的点做复杂度就没什么问题了。于是想到虚树。

虚树这种东西其实不是特别难,大概意思就是把所有要求的点按照$dfn$排序后依次考虑相邻两项的$lca$,用栈维护时分类讨论连边。

这道题的思路其实也不是特别难,但是代码是真的恶心。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define mod 1000000007
 4 #define S 400005
 5 int n,r[S],dep[S],eu[S],dfn[S],fir[S],l[S],to[S],ec,T,ST[19][S],bin[S],F[S];
 6 int p[S],pc,mu[S],phi[S],np[S],iv[S],sum[S],ans,sta[S],tp,rp[S],sphi[S];
 7 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
 8 int mo(int a){return a>=mod?a-mod:a;}
 9 void dfs(int p,int fa){
10     dep[p]=dep[fa]+1;eu[++T]=p;dfn[p]=T;
11     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p),eu[++T]=p;
12 }
13 int lca(int x,int y){
14     x=dfn[x];y=dfn[y];if(x>y)swap(x,y);
15     int B=bin[y-x+1];
16     return dep[ST[B][x]]<dep[ST[B][y-(1<<B)+1]]?ST[B][x]:ST[B][y-(1<<B)+1];
17 }
18 int cmp(int a,int b){return dfn[a]<dfn[b];}
19 void DFS(int p,int rat){
20     sphi[p]=0;
21     for(int i=fir[p];i;i=l[i])DFS(to[i],rat),sphi[p]=mo(sphi[p]+sphi[to[i]]);
22     rat=1ll*rat*dep[p]%mod;
23     for(int i=fir[p];i;i=l[i])
24         ans=mo(ans+mod-1ll*rat*sphi[to[i]]%mod*mo(mod+sphi[p]-sphi[to[i]])%mod),
25         ans=mo(ans+mod-2ll*rat%mod*sphi[to[i]]%mod*phi[p]*rp[p]%mod);
26     ans=mo(ans+mod-1ll*rp[p]*phi[p]*phi[p]%mod*rat%mod);
27     sphi[p]=mo(sphi[p]+phi[p]*rp[p]);
28     fir[p]=rp[p]=0;
29 }
30 int main(){
31     scanf("%d",&n);
32     for(int i=1,x;i<=n;++i)scanf("%d",&x),r[i]=x;
33     for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),link(r[a],r[b]),link(r[b],r[a]);
34     dfs(1,0);
35     for(int i=1;i<=T;++i)ST[0][i]=eu[i];
36     for(int i=1;i<=18;++i)for(int j=1<<i;j<1<<i+1&&j<=T;++j)bin[j]=i;
37     for(int i=1;i<=18;++i)for(int j=1;j+(1<<i)-1<=T;++j)
38         ST[i][j]=ST[i-1][dep[ST[i-1][j]]<dep[ST[i-1][j+(1<<i-1)]]?j:j+(1<<i-1)];
39     mu[1]=phi[1]=iv[1]=1;
40     for(int i=2;i<=n;++i){
41         if(!np[i])p[++pc]=i,mu[i]=-1,phi[i]=i-1;
42         for(int j=1,x;j<=pc&&(x=i*p[j])<=n;++j)
43             if(i%p[j])np[x]=1,mu[x]=-mu[i],phi[x]=phi[i]*(p[j]-1);
44             else{np[x]=1;phi[x]=phi[i]*p[j];break;}
45     }
46     for(int i=2;i<=n;++i)iv[i]=mod-1ll*mod/i*iv[mod%i]%mod;
47     for(int d=1;d<=n;++d)for(int g=d;g<=n;g+=d)
48         F[g]=(F[g]+1ll*d*iv[phi[d]]*mu[g/d]%mod)%mod,sum[d]=mo(sum[d]+phi[g]);
49     for(int i=1;i<=n;++i)F[i]=mo(F[i]%mod+mod),fir[i]=0;
50     for(int p=1;p<=n;++p){
51         int d=0,N=n/p,rt;ec=0;
52         for(int i=p;i<=n;i+=p)d=(d+1ll*dep[i]*phi[i])%mod,r[i/p]=i,rp[i]=1;
53         ans=(ans+2ll*d*sum[p]%mod*F[p])%mod;
54         sort(r+1,r+1+N,cmp);
55         rt=r[1];for(int i=2;i<=N;++i)rt=lca(rt,r[i]);tp=0;
56         for(int i=1,l;i<=N;++i){
57             if(!tp)goto E;
58             l=lca(r[i],sta[tp]);
59             if(l==sta[tp])goto E;
60             while(tp>1&&dfn[l]<=dfn[sta[tp-1]])link(sta[tp-1],sta[tp]),tp--;
61             if(sta[tp]!=l)link(l,sta[tp]),sta[tp]=l;
62 E:            sta[++tp]=r[i];
63         }while(tp>1)link(sta[tp-1],sta[tp]),tp--;
64         DFS(rt,mo(F[p]<<1));
65     }
66     printf("%lld
",1ll*ans*iv[n]%mod*iv[n-1]%mod);
67 }
View Code

T2:过河(river)

大意:送$n$猪过河,有$m$个三元关系,如果这三个在同一岸就非法。每次运一个可以往回运。问能否过河。$nle 1000,mle 3000$

如果所有三元关系的交集为空,一定非法,因为第一遍过去时剩在这一岸的一定会打架。

所以我们提出它们的交集,剩下一些二元组看成边。边上两点不能在同一岸,这些条件是否矛盾就看它是否存在奇环。

否则进行奇偶染色后就是一种合法的分岸方法。

特别的我们要考虑运那只特殊的猪,在它前后运的那两只并不会产生矛盾(因为特殊的猪在船上)

转化问题:给定图,去掉两个点之后是否为二分图。

暴力就是枚举两个点。要注意判断输入数据中三元环有元素相同的情况。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,fir[1001],l[6003],to[6003],a[3111],b[3111],c[3111],P,co[1111],ok,ec;
 4 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;l[++ec]=fir[b];fir[b]=ec;to[ec]=a;}
 5 void dfs(int p,int c){
 6     co[p]=c;
 7     for(int i=fir[p];i&&ok;i=l[i])if(!co[to[i]])dfs(to[i],c^1);
 8         else if(co[to[i]]==co[p])ok=0;
 9 }
10 int main(){//freopen("river1.in","r",stdin);
11     int t;cin>>t;while(t-->0){
12         cin>>n>>m;P=0;
13         for(int i=1;i<=m;++i){cin>>a[i]>>b[i]>>c[i];if(a[i]==b[i]||b[i]==c[i])i--,m--;}
14         for(int i=1;i<=n;++i){
15             for(int j=1;j<=m;++j)if(a[j]==i||b[j]==i||c[j]==i);else goto X;
16             P=i;X:;
17         }
18         if(!P){puts("no");continue;}
19         for(int i=1;i<=n;++i)if(i!=P)for(int j=i+1;j<=n;++j)if(j!=P){
20             for(int k=1;k<=n;++k)co[k]=fir[k]=0;ec=0;
21             for(int k=1;k<=m;++k)
22                 if(a[k]==P){if(b[k]!=i&&b[k]!=j&&c[k]!=i&&c[k]!=j)link(b[k],c[k]);}
23                 else if(b[k]==P){if(a[k]!=i&&a[k]!=j&&c[k]!=i&&c[k]!=j)link(a[k],c[k]);}
24                 else {if(b[k]!=i&&b[k]!=j&&a[k]!=i&&a[k]!=j)link(b[k],a[k]);}
25             ok=1;
26             for(int k=1;k<=n&&ok;++k)if(!co[k])dfs(k,2);
27             if(ok)goto Y;
28         }Y:puts(ok?"yes":"no");
29     }
30 }
View Code

正解是枚举去掉的第一个点,对于其余边建出$dfs$树,看哪些点能够成为被删的第二个点。

这个点需要存在在所有的奇环内。而所有的奇环在$dfs$树上的表现形式只有两种:

1,返祖边+树边。其中返祖边跨越的树上距离为偶数。

2,两条返祖边+树边。其中两条返祖边的树上距离一奇一偶。

对于第一种情况我们打一个差分标记记录就可以。

对于第二种情况,我们在判断点$p$时,要保证$p$的每一个儿子的子树不存在一奇一偶的返祖边。

注意这里所说的第二种情况是对于每一个儿子的子树考虑的,而不是所有儿子加起来。

第二种情况的判断方法我想$xm$学的大神做法,像$tarjan$一样记一个回溯值按照深度判就行了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,fir[1001],l[6003],to[6003],a[3111],b[3111],c[3111],P,ok,ec;
 4 int odd[1111],dep[1111],oddcnt,f[1111],Odd[1111],Even[1111];
 5 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;l[++ec]=fir[b];fir[b]=ec;to[ec]=a;}
 6 void dfs(int p,int fa){
 7     dep[p]=dep[fa]+1;f[p]=fa;
 8     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)
 9         if(!dep[to[i]])dfs(to[i],p),odd[p]+=odd[to[i]],Even[p]=min(Even[p],Even[to[i]]),Odd[p]=min(Odd[p],Odd[to[i]]);
10         else if(dep[p]-dep[to[i]]&1){if(dep[to[i]]<dep[p])Even[p]=min(Even[p],dep[to[i]]);}
11         else if(dep[to[i]]<dep[p])odd[p]++,odd[f[to[i]]]--,oddcnt++,Odd[p]=min(Odd[p],dep[to[i]]);
12 }
13 int main(){//freopen("river1.in","r",stdin);
14     int t;cin>>t;while(t-->0){
15         cin>>n>>m;P=0;
16         for(int i=1;i<=m;++i)cin>>a[i]>>b[i]>>c[i];
17         for(int i=1;i<=n;++i){
18             for(int j=1;j<=m;++j)if(a[j]==i||b[j]==i||c[j]==i);else goto X;
19             P=i;X:;
20         }
21         if(!P){puts("no");continue;}
22         for(int x=1;x<=n;++x){
23             for(int i=1;i<=n;++i)fir[i]=odd[i]=dep[i]=f[i]=0,Odd[i]=Even[i]=1234567;ec=1;oddcnt=ok=0;
24             for(int i=1;i<=m;++i)
25                 if(a[i]==P){if(b[i]!=x&&c[i]!=x)link(b[i],c[i]);}
26                 else if(b[i]==P){if(a[i]!=x&&c[i]!=x)link(a[i],c[i]);}
27                 else if(c[i]==P){if(a[i]!=x&&b[i]!=x)link(a[i],b[i]);}
28             for(int i=1;i<=n;++i)if(i!=x&&i!=P&&!dep[i])dfs(i,0);
29             for(int i=1;i<=n;++i)if(odd[i]==oddcnt){
30                 int r=1;
31                 for(int j=fir[i];j;j=l[j])if(dep[to[j]]>dep[i]&&Even[to[j]]<dep[i]&&Odd[to[j]]<dep[i])r=0;
32                 ok|=r;
33             }if(ok)break;
34         }puts(ok?"yes":"no");
35     }
36 }
View Code

T3:NPIO十合一

大意:无题面。给出$10$份超慢$std$与数据生成/输出生成代码,求解答案。

National Programming Informatic Olympic???

若答案数组为$c$。输出生成方式$x=(233 imes x   xor c[i])mod 1000000007$

$Test1:$读入数组$a,b$对位求和后输出。数组大小$10^9$

模拟题意生成数据并输出即可。预计耗时$18s$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     freopen("npio1.out","w",stdout);
 5     const int n=1000000000;register int x=233,y=233,res=0;
 6     for(int i=1;i<=n;++i)x=(37*x+666)%19260817;
 7     for(int i=1;i<=n;++i)
 8         x=(37*x+666)%19260817,
 9         y=(37*y+666)%19260817,
10         res=(233LL*res^x%10000+y%10000)%1000000007;
11     cout<<res<<endl;
12 }
View Code

$Test2:$读入数组$a,b$卷积后输出。数组大小$5000000$。值域$2^{15}$。常系数线性齐次递推生成。

可以$MTT/FFT?$我用的$Test3$的方法。预计耗时$2s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int bit=1<<15;
 4 int A[bit],B[bit],C[bit<<1];
 5 int main(){
 6     freopen("npio2.out","w",stdout);
 7     const int n=5000000;register int x=23333;
 8     for(int i=0;i<bit;++i)A[i]=x=(233*x+37)&32767;
 9     for(int i=bit;i<n;++i)x=(233*x+37)&32767;
10     for(int i=0;i<bit;++i)B[i]=x=(233*x+37)&32767;
11     for(int i=0;i<bit;++i)for(int j=0;j<bit;++j)C[i+j]=(C[i+j]+A[i]*B[j])%998244353;
12     register int ans=0;
13     for(int i=0;i<n;++i){
14         register int bl=i>>15,lw=i&32767,tmp=(C[lw]*(bl+1ll)+1ll*bl*C[lw|bit])%998244353;
15         if(i%1000000==0)cerr<<i<<endl;
16         ans=(ans*233LL^tmp)%1000000007;
17     }cout<<ans<<endl;
18 }
View Code

$Test3:$读入数组$a,b$卷积后输出。数组大小$10^9$。值域$2^{15}$。常系数线性齐次递推生成。

根据生成方式发现有循环节,打出来发现循环节恰好为$2^{15}$。于是直接做$2^{16}$的卷积就行了。

然后乘上错位的系数即可。预计耗时$28s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int bit=1<<15;
 4 int A[bit],B[bit],C[bit<<1];
 5 int main(){
 6     freopen("npio3.out","w",stdout);
 7     const int n=1000000000;register int x=23333;
 8     for(int i=0;i<bit;++i)A[i]=x=(233*x+37)&32767;
 9     for(int i=bit;i<n;++i)x=(233*x+37)&32767;
10     for(int i=0;i<bit;++i)B[i]=x=(233*x+37)&32767;
11     for(int i=0;i<bit;++i)for(int j=0;j<bit;++j)C[i+j]=(C[i+j]+A[i]*B[j])%998244353;
12     register int ans=0;
13     for(int i=0;i<n;++i){
14         register int bl=i>>15,lw=i&32767,tmp=(C[lw]*(bl+1ll)+1ll*bl*C[lw|bit])%998244353;
15         if(i%1000000==0)cerr<<i<<endl;
16         ans=(ans*233LL^tmp)%1000000007;
17     }cout<<ans<<endl;
18 }
View Code

$Test4:$排序$a$数组。数组大小与值域是$10^9$。

发现循环节很长。。。开$short$直接桶排,重复的数不多。预计耗时$45s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 short M[1000000001];
 4 int main(){
 5     freopen("npio4.out","w",stdout);
 6     unsigned int x=23333;
 7     for(int i=1;i<=1000000000;++i){
 8         x=x^(x<<13);
 9         x=x^(x>>17);
10         x=x^(x<<5);
11         M[x%1000000000]++;
12         if(i%100000==0)cerr<<i<<endl;
13     }int ans=0;
14     for(int i=0;i<1000000000;++i)while(M[i])
15         M[i]--,ans=(233LL*ans^i)%1000000007;
16     cout<<ans<<endl;
17 }
View Code

$Test5:$随机树。按序输出子树大小。数组大小$10^9$。常系数线性齐次递推生成。模数$233$进制数$2^{32}$

考场上没想出来。

应该算是最难的一个。可以发现模数与进制数互质,存在逆元$233^{2^{31}-1}$。

所以可以倒推回来存子树大小。大小数组对于较小的位置开$int$较大位置开$short$。$int$开得越多越好。

预计耗时$43s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 short d[1000000001];int D[270000001];
 4 inline int addd(register const int&p,register const int&w){
 5     if(p<=270000000)D[p]+=w;
 6     else d[p]+=w;
 7 }
 8 inline int deg(register const int&p){
 9     if(p<=270000000)return D[p];
10     else return (int)d[p];
11 }
12 int main(){
13     freopen("npio5.out","w",stdout);
14     const int n=1000000000;register unsigned int x=23333,iv=233,Iv=1;register int ans=0;
15     for(int i=0;i<31;++i)Iv*=iv,iv*=iv;iv=Iv;
16     for(int i=1;i<n;++i)x=233*x+37;
17     for(int i=1;i<=n;++i)addd(i,1);
18     for(int i=n-1;i;--i){
19         int fa=x%i+1;addd(fa,deg(i+1));
20         x-=37;x*=iv;
21         if(i%1000000==0)cerr<<i<<endl;
22     }
23     for(int i=1;i<=n;++i)ans=(233LL*ans^deg(i))%1000000007;
24     cout<<deg(1)<<' '<<ans<<endl;
25 }
View Code

$Test6:$随机基环树。随机树加一条边求最小生成树。数据范围$10^9$。值域$2^{15}$

最机智的做法取模$Dyyb$。因为值域只有$2^{15}$所以依次尝试去掉这个边权的边,和样例拍上就行。

我的弱智做法是因为随机树期望深度为$ln$级别,所以爆跳父亲求$lca$,找环上最小边。预计耗时$6s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int n=1000000000;
 4 int fx[11111],tfx[11111],fy[11111],tfy[11111],cfx,cfy,ans,r[4],tans;
 5 int main(){
 6     freopen("npio6.out","w",stdout);
 7     unsigned int x=23333,w=233,a,b;
 8     for(int i=1;i<n;++i)x=233*x+37,w=23*w+37&32767;
 9     x=a=233*x+37;b=233*x+37;ans=23*w+37&32767;
10     fx[0]=a=a%n+1,fy[0]=b=b%n+1;
11     //cout<<a<<' '<<b<<endl;
12     while(a!=1){
13         x=23333;w=233;cfx++;
14         for(int i=1;i<a;++i)x=233*x+37,w=(23*w+37)&32767;
15         a=fx[cfx]=x%(a-1)+1;tfx[cfx]=w;//cerr<<a<<endl;
16     }//cout<<cfx<<endl;
17     while(b!=1){
18         x=23333;w=233;cfy++;
19         for(int i=1;i<b;++i)x=233*x+37,w=(23*w+37)&32767;
20         b=fy[cfy]=x%(b-1)+1;tfy[cfy]=w;
21     }//cout<<cfy<<endl;
22     for(int i=0;i<=cfx;++i)for(int j=0;j<=cfy;++j)if(fx[i]==fy[j]){
23         for(int k=1;k<=i;++k)ans=max(ans,tfx[k]);
24         for(int k=1;k<=j;++k)ans=max(ans,tfy[k]);
25         goto O;
26     }O:
27     w=233;
28     long long nans=-ans;
29     for(int i=1;i<=n;++i)w=23*w+37&32767,nans+=w;
30     for(int i=0;i<4;++i)r[i]=nans%10000,nans/=10000;
31     for(int i=0;i<4;++i)tans=(tans*233LL^r[i])%1000000007;
32     cout<<tans<<endl;
33 }
View Code

$Test7:$维护堆支持插入/弹顶。每次操作后堆顶为答案。操作数及值域$10^9$。操作是随机的。

因为期望下弹与加次数相同,所以直接暴力模拟。元素个数始终没有超过$30000$所以不太慢。

预计耗时$1min$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 priority_queue<int>Q;
 4 const int n=1000000000,mod=1000000009;
 5 int main(){
 6     freopen("npio7.out","w",stdout);
 7     int sz=0,y=23333,ans=0;unsigned int x=233;
 8     for(int i=1;i<=n;++i){
 9         x=(x*23+777)%19260817;
10         if(sz<2||(!(x&1)))y=y*233+567,Q.push(y),++sz;
11         else Q.pop(),sz--;
12         if(i%10000000==0)cerr<<i<<' '<<sz<<endl;
13         ans=(233LL*ans^(Q.top()%mod+mod)%mod)%1000000007;
14     }cout<<ans<<endl;
15 }
View Code

$Test8:$动态加入数,每次加入后中位数为答案。操作数及值域$10^9$。数据随机。

考场上没想出来。

类似于原题。以前有一个是$2 imes 10^9$之内所有质数乘什么东西来着。

循环节还是很长,开$short$桶维护每个数出现次数,维护一个指针表示当前值与这个值的排名。

在随机数据下指针的移动次数很少。刚开始跑的慢后来密集之后很快。

预计耗时$70s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 short v[1000000000];
 4 int main(){freopen("npio8.out","w",stdout);
 5     const int n=1000000000;register unsigned int x=23333;
 6     register int p=0,rk=0,ans=0;
 7     for(int i=1;i<=n;++i){
 8         x=233*x+37;
 9         v[x%1000000000]++;
10         if(x%1000000000<p)rk++;
11         while(rk+v[p]<i+1>>1)rk+=v[p],p++;
12         while(rk+1>i+1>>1)p--,rk-=v[p];
13         ans=(233LL*ans^p)%1000000007;
14         if(i%10000000==0)cerr<<i<<endl;
15     }
16     cout<<ans<<endl;
17 }
View Code

$Test9:$动态加入数,每次加入后有多少种数即为答案。操作数及值域$10^9$。

$bitset$直接搞就可以。编译预计耗时$70s$。运行预计耗时$50s$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 bitset<1000000000>B;
 4 const int n=1000000000,mx=1000000000;
 5 int main(){
 6     freopen("npio9.out","w",stdout);
 7     register unsigned int x=23333,ans=0,r=0;
 8     for(int i=1;i<=n;++i){
 9         x=233*x+37;
10         if(!B[x%mx])ans++;
11         B[x%mx]=1;
12         if(i%10000000==0)cerr<<i<<' '<<ans<<endl;
13         r=(233LL*r^ans)%1000000007;
14     }cout<<r<<endl;
15 }
View Code

$Test10:$求各个点双中点的编号和,排序后依次输出。点数$10^7$。边数$10^9$。边随机。

生成方式为$x=x imes 233 +37,y=y imes 23+37$。$unsigned int$自然溢出。$x,y$初值为$23333,777$

考场上没想出来。

可以发现$x,y$的奇偶性时刻相同。所以奇点之间联通,偶点之间联通。

因为点少边多,所以在随机数据下每个联通块都是点双。

所以所有奇点在一个点双里,所有偶点在一个点双里。直接比较输出即可。

预计耗时$0s$

1 #include<bits/stdc++.h>
2 using namespace std;
3 int main(){
4     freopen("npio10.out","w",stdout);
5     register int x=5000001*5000000ll%998244353,y=5000000*5000000ll%998244353;
6     cout<<(233ll*y^x)%1000000007<<endl;
7 }
View Code

.

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12201188.html