bzoj 1002 轮状病毒 打表

来源:互联网 发布:六宫格切图软件 编辑:程序博客网 时间:2024/05/16 02:22

一眼看到数据范围,输入只有1个n,n<100果断打表。然而好像跑表的复杂度不兹磁啊,要跑几年。所以要打表找规律。

#include<iostream>//这是小数据打表#include<cstdio>using namespace std;struct E{int f,t;}b[100005];int cnt,n;int use[100005];int fa[100005];int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}int ans;void dfs(int x,int k){    if(k==n)    {        for(int i=0;i<=n;i++)            fa[i]=i;        bool h=1;        for(int i=1;i<=k;i++)        {            int p=use[i];            int x=b[p].f,y=b[p].t;            if(find(x)!=find(y))                fa[find(x)]=find(y);            else {h=0;break;}        }        if(h) ans++;        return ;    }    if(x>cnt) return ;    use[k+1]=x;    dfs(x+1,k+1);    dfs(x+1,k);}int main(){    for(n=1;n<=100;n++)    {        ans=0;cnt=0;        for(int i=1;i<n;i++)            b[++cnt]=(E){i,i+1};        b[++cnt]=(E){n,1};        for(int i=1;i<=n;i++)            b[++cnt]=(E){0,i};        dfs(1,0);cout<<n<<" "<<ans<<endl;    }}/*1 12 53 164 455 1216 3207 8418 22059 577610 1512511 3960112 10368013 27144114 71064515 186049616 487084517 1275204118 33385280*/

我打出n<=17的答案,想起在某学堂讲过自动找规律机,但我当时在颓废,于是硬生生的用眼瞪出了规律,合理猜想,大胆假设。对于奇数,答案都是某个数c【i】的平方。c[i]=c[i-2]*3-c[i-4];
对于偶数,答案是某个数c[i]除以5,c[i]=c[i-2]*7-c[i-4]+2;
然后是高精度。

#include<iostream>#include<cstdio>using namespace std;struct Big{    int a[10005];    int x;    void print()    {        bool pr=0;        for(int i=x+100;i>=1;i--)            if(a[i]||pr)printf("%d",a[i]),pr=1;    }    void pre()    {        for(int i=1;;i++)        {            if(i>x&&a[i]==0)            {                x=i-1;                break;            }            if(a[i]>9)            {                a[i+1]+=a[i]/10;                a[i]%=10;            }        }    }}f[105];Big operator *(Big A,int b){    int x=A.x;    for(int i=1;i<=x;i++)        A.a[i]*=b;    A.pre();    return A;}Big zero;Big operator *(Big A,Big B){    Big C=zero;    for(int i=1;i<=A.x;i++)    for(int j=1;j<=B.x;j++)        C.a[i+j-1]+=A.a[i]*B.a[j];    C.x=A.x+B.x;    C.pre();    return C;}Big operator -(Big A,Big B){    for(int i=1;i<=A.x;i++)    {        A.a[i]-=B.a[i];        if(A.a[i]<0)        {            A.a[i+1]--;            A.a[i]+=10;        }    }int x=0;    for(int i=A.x;i>=1;i--)    {        if(A.a[i])        {            x=i;            break;        }    }    A.x=x;    return A;}int main(){    int n;    scanf("%d",&n);    f[1].a[1]=1;f[3].a[1]=4;    f[2].a[1]=1;f[4].a[1]=9;    for(int i=1;i<=4;i++)        f[i].x=1;    if(n%2)    {        for(int i=5;i<=n;i+=2)            f[i]=f[i-2]*3-f[i-4];        f[n]=f[n]*f[n];        f[n].print();    }    else    {        for(int i=6;i<=n;i+=2)        {            f[i]=f[i-2]*7-f[i-4];            f[i].a[1]+=2;            f[i].pre();        }        f[n]=f[n]*5;        f[n].print();    }    return 0;}
5 1