【ZJOI2017 Round1练习&BZOJ4766】D1T2 文艺计算姬(Prufer编码)

题意:给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图K_{n,m},求其生成树个数 mod p。

100%的数据:1 <= n,m,p <= 10^18

思路:这是一道结论(打表找规律)+教你快速幂和乘法 题

结论为:S=n^(m-1)*m^(n-1)

需要注意的是n,m过大,普通的快速幂与乘法会炸

所以需要手写乘法,类似于快速幂的形式将其转换为加法

2017.2.28:%%%CC的证明:

设两边为X侧,Y侧

考虑它们在Prufer序列中出现的位置与取值种数

生成树的最后一条边一定链接一个X侧一个Y侧点

一个X侧点的插入就代表一个Y侧点被删除

因为最后只剩一个X侧点一个Y侧点

所以X侧点会出现M-1次,每次出现有N种取值,每个X侧点可以重复出现

所以对于X侧点有n^(m-1)种取值

Y侧点同理

得证

 1 var n,m,mo:int64;
 2 
 3 function clac(x,y:int64):int64;
 4 begin
 5  clac:=0;
 6  while y>0 do
 7  begin
 8   if y and 1=1 then clac:=(clac+x) mod mo;
 9   x:=(x+x) mod mo;
10   y:=y>>1;
11  end;
12 end;
13 
14 function mult(x,y:int64):int64;
15 begin
16  mult:=1;
17  while y>0 do
18  begin
19   if y and 1=1 then mult:=clac(mult,x) mod mo;
20   x:=clac(x,x) mod mo;
21   y:=y>>1;
22  end;
23 end;
24 
25 begin
26  assign(input,'art.in'); reset(input);
27  assign(output,'art.out'); rewrite(output);
28  readln(n,m,mo);
29  writeln(clac(mult(n,m-1),mult(m,n-1)));
30  close(input);
31  close(output);
32 end.

 

posted on 2017-02-28 14:22  myx12345  阅读(230)  评论(0编辑  收藏  举报

导航