POJ:1737

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/ShellDawn/article/details/80658244
POJ