生成树的计数(基尔霍夫矩阵):BZOJ 1002 [FJOI2007]轮状病毒
1002: [FJOI2007]轮状病毒
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3928 Solved: 2154
[Submit][Status][Discuss]
Description
轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子
和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示
N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示
现给定n(N<=100),编程计算有多少个不同的n轮状病毒
Input
第一行有1个正整数n
Output
计算出的不同的n轮状病毒数输出
Sample Input
3
Sample Output
16
纯属娱乐~~~
1 #ifndef EXTINT_H 2 #define EXTINT_H 3 4 #include <cctype> 5 #include <string> 6 #include <istream> 7 #include <ostream> 8 #include <cassert> 9 #include <iomanip> 10 #include <iostream> 11 12 class ExtInt{ 13 friend ExtInt operator +(const ExtInt &a, const ExtInt &b); 14 friend ExtInt operator -(const ExtInt &a, const ExtInt &b); 15 friend ExtInt operator *(const ExtInt &a, const ExtInt &b); 16 friend ExtInt operator /(const ExtInt &a, const ExtInt &b); 17 friend ExtInt operator %(const ExtInt &a, const ExtInt &b); 18 friend bool operator <(const ExtInt &a, const ExtInt &b); 19 friend bool operator >(const ExtInt &a, const ExtInt &b); 20 friend bool operator <=(const ExtInt &a, const ExtInt &b); 21 friend bool operator >=(const ExtInt &a, const ExtInt &b); 22 friend bool operator ==(const ExtInt &a, const ExtInt &b); 23 friend bool operator !=(const ExtInt &a, const ExtInt &b); 24 friend std::istream & operator >>(std::istream &inputStream, ExtInt &data); 25 friend std::ostream & operator <<(std::ostream &outputStream, const ExtInt &data); 26 private: 27 static const int LIMIT = 1000000000; 28 static const int WIDTH = 9; 29 int length; 30 bool isNegative; 31 struct DListNode{ 32 int data; 33 DListNode *forward, *next; 34 DListNode(int data = 0) : data(data), forward(NULL), next(NULL) {} 35 DListNode & remove(); 36 DListNode & append(DListNode *data); 37 DListNode & append(const int &data); 38 DListNode & insert(DListNode *data); 39 DListNode & insert(const int &data); 40 }*low, *high; 41 public: 42 ExtInt(int data = 0); 43 ExtInt(const ExtInt &rhs); 44 ExtInt(const std::string &rhs); 45 virtual ~ExtInt(); 46 47 ExtInt & operator =(const ExtInt &rhs); 48 ExtInt & operator +=(const ExtInt &rhs); 49 ExtInt & operator -=(const ExtInt &rhs); 50 ExtInt & operator *=(const ExtInt &rhs); 51 ExtInt & operator /=(const ExtInt &rhs); 52 ExtInt & operator %=(const ExtInt &rhs); 53 //ExtInt & operator ++(); 54 //ExtInt & operator ++(int); 55 //ExtInt & operator --(); 56 //ExtInt & operator --(int); 57 }; 58 59 60 #endif 61 62 63 ExtInt::DListNode & ExtInt::DListNode::remove() { 64 DListNode *tmp = this -> forward; 65 tmp -> forward -> next = this; 66 this -> forward = tmp -> forward; 67 delete tmp; 68 return *this; 69 } 70 ExtInt::DListNode & ExtInt::DListNode::append(DListNode *data) { 71 data -> next = this -> next; 72 data -> forward = this; 73 if (this -> next != NULL) { 74 this -> next -> forward = data; 75 } 76 this -> next = data; 77 return *this; 78 } 79 ExtInt::DListNode & ExtInt::DListNode::append(const int &data) { 80 return append(new DListNode(data)); 81 } 82 ExtInt::DListNode & ExtInt::DListNode::insert(DListNode *data) { 83 data -> next = this; 84 data -> forward = this -> forward; 85 if (this -> forward != NULL) { 86 this -> forward -> next = data; 87 } 88 this -> forward = data; 89 return *this; 90 } 91 ExtInt::DListNode & ExtInt::DListNode::insert(const int &data) { 92 return insert(new DListNode(data)); 93 } 94 95 ExtInt::ExtInt(int data) { 96 low = new DListNode; 97 high = new DListNode; 98 low -> append(high); 99 length = 0; 100 isNegative = false; 101 if (data < 0) { 102 isNegative = true; 103 data = -data; 104 } 105 while (data >= ExtInt::LIMIT) { 106 high -> insert(data % ExtInt::LIMIT); 107 data /= ExtInt::LIMIT; 108 length++; 109 } 110 if (length == 0 || data > 0) { 111 high -> insert(data); 112 length++; 113 } 114 } 115 ExtInt::ExtInt(const ExtInt &rhs) { 116 low = new DListNode; 117 high = new DListNode; 118 low -> append(high); 119 length = 0; 120 isNegative = rhs.isNegative; 121 for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) { 122 high -> insert(it -> data); 123 length++; 124 } 125 } 126 ExtInt::ExtInt(const std::string &rhs) { 127 low = new DListNode; 128 high = new DListNode; 129 low -> append(high); 130 length = 0; 131 isNegative = false; 132 if (rhs[0] == '-') { 133 isNegative = true; 134 } 135 for (int i = rhs.length() - 1; i >= 0; i -= WIDTH) { 136 int value = 0; 137 for (int j = std::max(0, i - WIDTH + 1); j <= i; j++) { 138 if (j == 0 && isNegative) continue; 139 assert(isdigit(rhs[j])); 140 value = value * 10 + rhs[j] - '0'; 141 } 142 high -> insert(value); 143 length++; 144 } 145 while (length > 1 && high -> forward -> data == 0) { 146 high -> remove(); 147 length--; 148 } 149 } 150 ExtInt & ExtInt::operator =(const ExtInt &rhs) { 151 if (this == &rhs) return *this; 152 if (low != NULL || high != NULL) { 153 this -> ~ExtInt(); 154 } 155 low = new DListNode; 156 high = new DListNode; 157 low -> append(high); 158 length = 0; 159 isNegative = rhs.isNegative; 160 for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) { 161 high -> insert(it -> data); 162 length++; 163 } 164 return *this; 165 } 166 ExtInt::~ExtInt() { 167 for (DListNode *it = low; it != NULL;) { 168 DListNode *tmp = it -> next; 169 delete it; 170 it = tmp; 171 } 172 } 173 174 std::istream & operator >>(std::istream &inputStream, ExtInt &data) { 175 std::string tmp; 176 inputStream >> tmp; 177 data = ExtInt(tmp); 178 return inputStream; 179 } 180 std::ostream & operator <<(std::ostream &outputStream, const ExtInt &data) { 181 if (data.isNegative) { 182 outputStream << "-"; 183 } 184 ExtInt::DListNode *it = data.high -> forward; 185 outputStream << it -> data; 186 for (it = it -> forward; it != data.low; it = it -> forward) { 187 outputStream << std::setfill('0') << std::setw(ExtInt::WIDTH) << it -> data; 188 } 189 return outputStream; 190 } 191 192 bool operator <(const ExtInt &a, const ExtInt &b) { 193 if (a.isNegative && !b.isNegative) return true; 194 if (!a.isNegative && b.isNegative) return false; 195 bool flag = false; 196 if (a.isNegative && b.isNegative) flag = true; 197 if (a.length < b.length) return flag ^ true; 198 if (a.length > b.length) return flag ^ false; 199 ExtInt::DListNode *itA = a.high, *itB = b.high; 200 for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) { 201 if (itA -> data < itB -> data) return flag ^ true; 202 if (itA -> data > itB -> data) return flag ^ false; 203 } 204 return false; 205 } 206 bool operator >(const ExtInt &a, const ExtInt &b) { 207 if (a.isNegative && !b.isNegative) return false; 208 if (!a.isNegative && b.isNegative) return true; 209 bool flag = false; 210 if (a.isNegative && b.isNegative) flag = true; 211 if (a.length < b.length) return flag ^ false; 212 if (a.length > b.length) return flag ^ true; 213 ExtInt::DListNode *itA = a.high, *itB = b.high; 214 for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) { 215 if (itA -> data < itB -> data) return flag ^ false; 216 if (itA -> data > itB -> data) return flag ^ true; 217 } 218 return false; 219 } 220 bool operator >=(const ExtInt &a, const ExtInt &b) { 221 return !(a < b); 222 } 223 bool operator <=(const ExtInt &a, const ExtInt &b) { 224 return !(a > b); 225 } 226 bool operator ==(const ExtInt &a, const ExtInt &b) { 227 if (a.isNegative != b.isNegative) return false; 228 if (a.length != b.length) return false; 229 ExtInt::DListNode *itA = a.low, *itB = b.low; 230 for (; itA != a.high && itB != b.high; itA = itA -> next, itB = itB -> next) { 231 if (itA -> data != itB -> data) return false; 232 } 233 return true; 234 } 235 bool operator !=(const ExtInt &a, const ExtInt &b) { 236 return !(a == b); 237 } 238 239 ExtInt operator +(const ExtInt &a, const ExtInt &b) { 240 if (b.isNegative) { 241 ExtInt tmp = b; 242 tmp.isNegative = false; 243 return a - tmp; 244 } 245 if (a.isNegative) { 246 ExtInt tmp = a; 247 tmp.isNegative = false; 248 return b - tmp; 249 } 250 ExtInt ret = a; 251 ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next; 252 for (; itB != b.high; itA = itA -> next, itB = itB -> next) { 253 if (itA == ret.high) { 254 itA -> insert(0); 255 ret.length++; 256 itA = itA -> forward; 257 } 258 itA -> data += itB -> data; 259 if (itA -> data >= ExtInt::LIMIT) { 260 if (itA -> next == ret.high) { 261 itA -> append(0); 262 ret.length++; 263 } 264 itA -> next -> data += itA -> data / ExtInt::LIMIT; 265 itA -> data %= ExtInt::LIMIT; 266 } 267 } 268 return ret; 269 } 270 ExtInt operator -(const ExtInt &a, const ExtInt &b) { 271 if (b.isNegative) { 272 ExtInt tmp = b; 273 tmp.isNegative = false; 274 return a + tmp; 275 } 276 if (a.isNegative) { 277 ExtInt tmp = a; 278 tmp.isNegative = false; 279 tmp = tmp + b; 280 tmp.isNegative = true; 281 return tmp; 282 } 283 if (a < b) { 284 ExtInt tmp = b - a; 285 tmp.isNegative = true; 286 return tmp; 287 } 288 ExtInt ret = a; 289 ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next; 290 for (; itA != ret.high && itB != b.high; itA = itA -> next, itB = itB -> next) { 291 itA -> data -= itB -> data; 292 if (itA -> data < 0) { 293 itA -> data += ExtInt::LIMIT; 294 itA -> next -> data--; 295 } 296 } 297 for (; itA != ret.high; itA = itA -> next) { 298 if (itA -> data < 0) { 299 itA -> data += ExtInt::LIMIT; 300 itA -> next -> data--; 301 } 302 } 303 while (ret.length > 1 && ret.high -> forward -> data == 0) { 304 ret.high -> remove(); 305 ret.length--; 306 } 307 return ret; 308 } 309 ExtInt operator *(const ExtInt &a, const ExtInt &b) { 310 if (a == ExtInt(0) || b == ExtInt(0)) return ExtInt(0); 311 ExtInt ret, tmp; 312 ExtInt::DListNode *itB = b.low -> next; 313 for (int value = 0; itB != b.high; itB = itB -> next, value++) { 314 if (itB -> data == 0) { 315 continue; 316 } 317 tmp = a; 318 ExtInt::DListNode *itA = tmp.low -> next; 319 for (long long r = 0; itA != tmp.high; itA = itA -> next) { 320 long long now = 1ll * itA -> data * itB -> data + r; 321 itA -> data = now % ExtInt::LIMIT; 322 r = 0; 323 if (now >= ExtInt::LIMIT) { 324 if (itA -> next == tmp.high) { 325 itA -> append(0); 326 tmp.length++; 327 } 328 r = now / ExtInt::LIMIT; 329 } 330 } 331 for (int i = 1; i <= value; i++) { 332 tmp.low -> append(0); 333 tmp.length++; 334 } 335 //std::cerr << ret << std::endl; 336 //std::cerr << tmp << std::endl; 337 //std::cerr << tmp.length << std::endl; 338 ret = ret + tmp; 339 } 340 ret.isNegative = a.isNegative ^ b.isNegative; 341 return ret; 342 } 343 ExtInt operator /(const ExtInt &a, const ExtInt &b) { 344 assert(b != ExtInt(0)); 345 if (a == ExtInt(0)) return ExtInt(0); 346 ExtInt ret, tmp, div = b; 347 ret.high -> remove(); 348 ret.length = 0; 349 tmp.high -> remove(); 350 tmp.length = 0; 351 div.isNegative = false; 352 ExtInt::DListNode *itA = a.high -> forward; 353 for (; itA != a.low; itA = itA -> forward) { 354 tmp.low -> append(itA -> data); 355 tmp.length++; 356 if (tmp >= div) { 357 int left = 0, right = ExtInt::LIMIT - 1; 358 while (left < right) { 359 int middle = (left + right >> 1) + 1; 360 if (tmp >= div * middle) { 361 left = middle; 362 } else { 363 right = middle - 1; 364 } 365 } 366 //std::cerr << tmp << " " << div * left << std::endl; 367 ret.low -> append(left); 368 ret.length++; 369 tmp = tmp - div * left; 370 } else { 371 ret.low -> append(0); 372 ret.length++; 373 } 374 if (tmp == ExtInt(0)) { 375 tmp.high -> remove(); 376 tmp.length = 0; 377 } 378 } 379 while (ret.length > 1 && ret.high -> forward -> data == 0) { 380 ret.high -> remove(); 381 ret.length--; 382 } 383 ret.isNegative = a.isNegative ^ b.isNegative; 384 if (ret.isNegative && tmp.low -> next != tmp.high) { 385 ret = ret - 1; 386 } 387 return ret; 388 } 389 ExtInt operator %(const ExtInt &a, const ExtInt &b) { 390 return a - a / b * b; 391 } 392 393 ExtInt & ExtInt::operator +=(const ExtInt &rhs) { 394 *this = *this + rhs; 395 return *this; 396 } 397 ExtInt & ExtInt::operator -=(const ExtInt &rhs) { 398 *this = *this - rhs; 399 return *this; 400 } 401 ExtInt & ExtInt::operator *=(const ExtInt &rhs) { 402 *this = *this * rhs; 403 return *this; 404 } 405 ExtInt & ExtInt::operator /=(const ExtInt &rhs) { 406 *this = *this / rhs; 407 return *this; 408 } 409 ExtInt & ExtInt::operator %=(const ExtInt &rhs) { 410 *this = *this % rhs; 411 return *this; 412 } 413 #include <iostream> 414 #include <cstdio> 415 using namespace std; 416 int n; 417 const int maxn=110; 418 ExtInt C[maxn][maxn]; 419 void abs(ExtInt &x){ 420 if(x<0)x=x*(-1); 421 } 422 void Solve(){ 423 for(int i=1;i<n;i++){ 424 for(int j=i+1;j<n;j++) 425 while(C[j][i]!=0){ 426 ExtInt r=C[i][i]/C[j][i]; 427 for(int k=i;k<n;k++) 428 C[i][k]-=C[j][k]*r; 429 swap(C[i],C[j]); 430 } 431 } 432 ExtInt ans=1; 433 for(int i=1;i<n;i++) 434 ans*=C[i][i]; 435 abs(ans); 436 cout<<ans<<endl; 437 return; 438 } 439 int main(){ 440 scanf("%d",&n);n++; 441 if(n!=2) 442 for(int i=1;i<n;i++){ 443 C[i][i%(n-1)+1]-=1; 444 C[i%(n-1)+1][i]-=1;C[i][i]+=1; 445 C[i%(n-1)+1][i%(n-1)+1]+=1; 446 } 447 for(int i=1;i<n;i++){ 448 C[i][n]=-1; 449 C[n][i]=-1; 450 C[i][i]+=1; 451 C[n][n]+=1; 452 } 453 Solve(); 454 return 0; 455 }
尽最大的努力,做最好的自己!