[BZOJ]1005 明明的烦恼(HNOI2008)

题解传送门

传送门2

题解写得非常好啊。

然后就是裸的高精了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
const int maxn=1000+5;
int n,sum,cnt,d[maxn],a[3005],tp[3005],fl;
using namespace std;
int gchengd(int a[],int b,int c[]) {
    int tp=0;
    for(int i=1;i<=a[0];i++) {
        c[i]=(a[i]*b+tp)%10;
        tp=(a[i]*b+tp)/10;
    }
    while(tp) {
        c[++a[0]]=tp%10;
        tp/=10;
    }
    for(int i=1;i<=a[0];i++) a[i]=c[i];
}
int gchud(int a[],int b,int c[]) {
    int tp=0;
    for(int i=a[0];i>=1;i--) {
        c[i]=(a[i]+tp*10)/b;
        tp=(a[i]+tp*10)%b;
    }
    for(int i=a[0];i>=1;i--) {if((i==a[0]&&c[i]==0)||(c[i]==c[i+1]&&c[i]==0)) a[0]--; else break;}
    for(int i=1;i<=a[0];i++) 
        a[i]=c[i];
}
int main()
{
    //freopen("","r",stdin);
    //freopen("","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&d[i]);
        if(d[i]==0) fl=1;
        else if(d[i]!=-1) cnt++,sum+=d[i]-1;
    }
    if(n==1||n==2) {
        if(n==1) {if(d[1]==-1) cout<<1<<endl; else cout<<0<<endl;}
        else if(n==2) {if(d[1]==-1&&d[2]==-1) cout<<1<<endl; else cout<<0<<endl;}
        return 0;
    }
    if(sum>n-2) fl=1;
    if(cnt==n&&sum<n-2) fl=1;
    if(fl) cout<<0<<endl;
    else {
        a[0]=a[1]=1;
        for(int i=1;i<=n-2;i++) 
            gchengd(a,i,tp);
        for(int i=1;i<=n-2-sum;i++) { 
            gchengd(a,n-cnt,tp); 
            gchud(a,i,tp);
        }
        for(int i=1;i<=n;i++) if(d[i]!=-1&&d[i]-1) {
            for(int j=2;j<=d[i]-1;j++)
            gchud(a,j,tp);
        }
        for(int i=a[0];i>=1;i--) 
            printf("%d",a[i]);
        printf("
");
    }
    return 0;
}
View Code