BZOJ2560 串珠子
阿新 • • 發佈:2018-06-05
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 串珠子