1. 程式人生 > >【nyoj-127】星際之門(一)(Cayley公式 / Prufer序列)

【nyoj-127】星際之門(一)(Cayley公式 / Prufer序列)

星際之門(一)

時間限制:3000 ms  |  記憶體限制:65535 KB

難度:3

描述

公元3000年,子虛帝國統領著N個星系,原先它們是靠近光束飛船來進行旅行的,近來,X博士發明了星際之門,它利用蟲洞技術,一條蟲洞可以連通任意的兩個星系,使人們不必再待待便可立刻到達目的地。

帝國皇帝認為這種發明很給力,決定用星際之門把自己統治的各個星系連結在一起。

可以證明,修建N-1條蟲洞就可以把這N個星系連結起來。

現在,問題來了,皇帝想知道有多少種修建方案可以把這N個星系用N-1條蟲洞連結起來?

輸入

第一行輸入一個整數T,表示測試資料的組數(T<=100)
每組測試資料只有一行,該行只有一個整數N,表示有N個星系。(2<=N<=1000000)

輸出

對於每組測試資料輸出一個整數,表示滿足題意的修建的方案的個數。輸出結果可能很大,請輸出修建方案數對10003取餘之後的結果。

樣例輸入

2
3
4

樣例輸出

3
16

思路:

題意很簡單,就是如果有n個點,能生成多少種不同的樹,這道題目實際就是考察Purfer序列應用(Purfer序列的部落格),一顆n個結點的樹,轉成一個Purfer序列後,序列的元素有n-2個,而一棵樹和一種序列是一一對應的(一棵n個節點的無根樹唯一地對應了一個長度為n-2的數列),因此要問能產生多少樹,只要看序列的種類數,序列有n-2個位置,每個位置上 的元素有n種(序列中是允許有重複元素的),因此序列的種類即不同的樹的種類有n^{n-2}

種。如果明白這一步後,那麼剩下的就是單純考察一個快速冪取模了。

Cayley定理:有n個節點的完全圖的生成樹的數量是n^{n-2},或者說n個節點的帶標號的無根樹有n^{n-2}個。

Prufer編碼:給定一棵帶標號的無根樹,找出編號最小的葉子節點,寫下與它相鄰的節點的編號,然後刪掉這個葉子節點。反覆執行這個操作直到只剩兩個節點為止。

一個有趣的推廣是,n個節點的度依次為D1, D2, …, Dn的無根樹共有(n-2)! / [ (D1-1)!(D2-1)!..(Dn-1)! ]個,因為此時Prüfer編碼中的數字i恰好出現Di-1次。(轉自此部落格

ac程式碼:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<set>
#include<iostream>
#include<map>
#include<stack>
#include<cmath>
#include<algorithm>
#define ll long long
#define mod 10003
#define eps 1e-8
using namespace std;
ll qsm(ll a,ll b)
{
	ll t=1;
	while(b)
	{
		if(b&1)
		{
			t=(t*a)%mod;
		}
		a=(a*a)%mod;
		b>>=1;
	}
	return t%mod;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		printf("%lld\n",qsm(n,n-2));
	}
	return 0;
}