版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ShellDawn/article/details/80658244
楼教主男人八题中的第一题:
最大50座不同城市,组成全联通图的数量,不取模。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#define maxn 55
std::vector<long long> C[maxn][maxn]; // 组合数
std::vector<long long> P[maxn*maxn]; // 2的n次幂
bool Pc[maxn]; // 幂级数染色
std::vector<long long> ans[maxn]; // 图的数量
bool ansc[maxn]; // ans染色
const long long BASE = 100000000; // 进制
void print(const std::vector<long long> &x) {
int l = x.size();
if( l == 0) printf("0\n");
else{
printf("%lld",x[l-1]);
for(int i = l - 2; i >= 0; i--){
printf("%08lld",x[i]);
}
printf("\n");
}
}
void assignment(std::vector<long long> &x,long long y){
x.clear();
while(y > 0){
x.push_back(y % BASE);
y /= BASE;
}
}
void addv(std::vector<long long> &z,const std::vector<long long> &x,const std::vector<long long> &y){
z.clear();
for(long long i = 0, g = 0; ; i++){
if( g == 0 && i >= x.size() && i >= y.size()) break;
long long t = g;
if( i < x.size()) t += x[i];
if( i < y.size()) t += y[i];
z.push_back(t % BASE);
g = t / BASE;
}
}
void minusv(std::vector<long long> &z,const std::vector<long long> &x,const std::vector<long long> &y){
z.clear();
long long g = 0;
for(int i = 0; i < x.size() ; i++){
long long t = 0;
if(i < y.size()) t += y[i];
if(x[i] - g < t){ z.push_back(BASE - t + x[i] - g); g = 1;}
else{ z.push_back(x[i] - g - t); g = 0;}
}
int loc = (int)z.size() - 1;
while(loc>=0&&loc<z.size()){
if(z[loc--] == 0) z.pop_back();
else break;
}
}
void multilong(std::vector<long long> &z, long long x,const std::vector<long long> &y){
z.clear();
long long t = 0;
for(int i = 0; i < y.size(); i++){
t += y[i] * x;
z.push_back( t % BASE );
t /= BASE;
}
if(t!=0) z.push_back(t);
}
void multi(std::vector<long long> &z,const std::vector<long long> &x,const std::vector<long long> &y){
z.clear();
std::vector<long long> t;
std::vector<long long> zt;
for(int i = 0; i < x.size(); i++){
multilong(t,x[i],y);
t.insert(t.begin(),i,0);
addv(zt,t,z);
z = zt;
}
}
void f(int y);
// 2^(y*(y-2)/2)
void h(int y){
if(!Pc[y]){
std::vector<long long> p;
assignment(P[y],1);
assignment(p,2);
std::vector<long long> Pt;
for(int i = y*(y-1)/2; i > 0 ; i>>=1){
if(i & 1){ multi(Pt,p,P[y]); P[y] = Pt;}
multi(Pt,p,p);
p = Pt;
}
Pc[y] = true;
}
}
//
void g(std::vector<long long> &z,int y){
std::vector<long long> x;
std::vector<long long> t;
for(int i = 1; i < y; i++){
f(i);
h(y-i);
multi(x,P[y-i],ans[i]);
multi(t,C[y-1][i-1],x);
addv(x,z,t);
z = x;
}
}
void f(int y){
if(!ansc[y]){
std::vector<long long> gv;
h(y);
g(gv,y);
minusv(ans[y],P[y],gv);
ansc[y] = true;
}
}
int main(){
memset(C,0,sizeof(C));
memset(ansc,0,sizeof(ansc));
memset(Pc,0,sizeof(Pc));
// 组合数
for(int i = 1; i < 51; i++){
assignment(C[i][0],1);
assignment(C[i][i],1);
for(int j = 1; j < i; j++){
addv(C[i][j],C[i-1][j-1],C[i-1][j]);
}
}
// 30ms
//freopen("input.txt","r",stdin);
//freopen("output0.txt","w",stdout);
int n;
while(scanf("%d",&n) != EOF && n){
//double timeS = (double)clock();
if(ansc[n]) print(ans[n]);
else{ f(n); print(ans[n]);}
//printf("time:%fms\n",(double)clock() - timeS);
}
return 0;
}