1. 程式人生 > >BZOJ2560 串珠子

BZOJ2560 串珠子

Go des return 正整數 設定 方案 NPU sta span

BZOJ2560 串珠子

Description

  銘銘有n個十分漂亮的珠子和若幹根顏色不同的繩子。現在銘銘想用繩子把所有的珠子連接成一個整體。
  現在已知所有珠子互不相同,用整數1到n編號。對於第i個珠子和第j個珠子,可以選擇不用繩子連接,或者在ci,j根不同顏色的繩子中選擇一根將它們連接。如果把珠子看作點,把繩子看作邊,將所有珠子連成一個整體即為所有點構成一個連通圖。特別地,珠子不能和自己連接。
  銘銘希望知道總共有多少種不同的方案將所有珠子連成一個整體。由於答案可能很大,因此只需輸出答案對1000000007取模的結果。

 

Input

 標準輸入。輸入第一行包含一個正整數n,表示珠子的個數。接下來n行,每行包含n個非負整數,用空格隔開。這n行中,第i行第j個數為ci,j。

 

Output

 標準輸出。輸出一行一個整數,為連接方案數對1000000007取模的結果。

Sample Input

3
0 2 3
2 0 4
3 4 0

Sample Output

50

HINT

  對於100%的數據,n為正整數,所有的ci,j為非負整數且不超過1000000007。保證ci,j=cj,i。每組數據的n值如下表所示。
編號 1 2 3 4 5 6 7 8 9 10
n 8 9 9 10 11 12 13 14 15 16

Source

2012國家集訓隊Round 1 day1

Solution

這道題好煩啊....

因為n只有16,可以狀壓

設定兩個數組g[]和f[],分別表示任意連邊的方案數和聯通圖的方案數。

我們可以找到狀態i的去最大一位的所有點,因為這個的肯定被求過。

枚舉這個的子集,然後減去g[這些子集]*f[枚舉的i^這些子集](見代碼),就可以求出。

Code


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cstdlib>
#include<algorithm> #define LL long long using namespace std; int n,k; const int mod=10000; int f[1005][1005]; int main() { cin>>n>>k; for(int i=1;i<=n;i++) f[i][0]=1; for(int i=2; i<=n; i++) { LL sum=0; for(int j=0; j<=k; j++) { (sum+=f[i-1][j])%mod; f[i][j]=sum%mod; if(j-i+1>=0) ((sum-=f[i-1][j-i+1])+mod)%mod; } } cout<<f[n][k]; return 0; }

BZOJ2560 串珠子