[FJOI2007]轮状病毒(bzoj1002)(递推+高精度)

传送门

其实这道题是生成树的计数问题,可以用个什么Matrix-Tree定理

然鹅我不会

看了这篇博客

打表找规律什么的真的是大佬!!!

从别人那儿扒到递推式:f[i]=f[i-1]*3-f[i-2]+2

因为会炸LL,所以用高精度。

#include<bits/stdc++.h> 
#define LL long long
using namespace std;
int read()
{
    int f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
struct bg{
    int w[101];
}f[103];
bg jian(bg a,bg b)
{
    a.w[1]+=2;
    int j=1;
    while(a.w[j]>=10){a.w[j]%=10;a.w[j+1]++;j++;}
    for(int i=1;i<=a.w[0];++i)
    {
        a.w[i]-=b.w[i];
        if(a.w[i]<0)a.w[i]+=10,a.w[i+1]--;
    }
    while(a.w[a.w[0]]==0)a.w[0]--;
    return a;
}
bg mul(bg a,int k)
{
    for(int i=1;i<=a.w[0];++i)
      a.w[i]*=k;
    for(int i=1;i<=a.w[0];++i)
    {
        a.w[i+1]+=a.w[i]/10;
        a.w[i]%=10;
    }
    while(a.w[a.w[0]+1]!=0)a.w[0]++;
    return a;
}
int main()
{//f[i]=f[i-1]*3-f[i-2]+2 
    int n=read();
    if(n==1){printf("1\n");return 0;}
    if(n==2){printf("5\n");return 0;}
    if(n==3){printf("16\n");return 0;}
    f[1].w[0]=f[2].w[0]=1;
    f[1].w[1]=1;f[2].w[1]=5;
    for(int i=3;i<=n;++i)
      f[i]=jian(mul(f[i-1],3),f[i-2]);
    for(int i=f[n].w[0];i>=1;--i)
      printf("%d",f[n].w[i]);
}
/*
4
2 3
3 1
6 1
0 2
*/
View Code

猜你喜欢

转载自www.cnblogs.com/yyys-/p/11436645.html
今日推荐