• [NOI2007]生成树计数环形版


    NOI2007这道题人类进化更完全之后出现了新的做法

    毕姥爷题解:

    于是毕姥爷出了一道环形版的这题(test0814),让我们写这个做法

    环形的情况下,k=5的时候是162阶递推。

    求这个递推可以用BM算法

    一个很好的介绍BM算法的博客

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int p=65521;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int k;
    20 
    21 template<typename T>void read(T &x)  {
    22     char ch=getchar(); x=0; T f=1;
    23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    24     if(ch=='-') f=-1,ch=getchar();
    25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    26 }
    27 
    28 LL a[1007][1007];
    29 LL solve(int n) {
    30     LL rs=1,f=1;
    31     For(i,1,n) For(j,1,n) a[i][j]=(a[i][j]+p)%p;
    32     For(i,1,n) {
    33         For(j,i+1,n) {
    34             LL A=a[i][i],B=a[j][i],t;
    35             while(B) {
    36                 t=A/B;
    37                 For(k,i,n) a[i][k]=(a[i][k]-t*a[j][k]%p+p)%p;
    38                 For(k,i,n) swap(a[i][k],a[j][k]);
    39                 A%=B; swap(A,B); f=-f;
    40             }
    41         }
    42         rs=rs*a[i][i]%p;
    43     }
    44     if(f==-1) rs=p-rs;
    45     return rs;
    46 }
    47 
    48 #define ANS
    49 int main() {
    50 #ifdef ANS
    51     //freopen("shanghai.in","r",stdin);
    52     freopen("biao.out","w",stdout);
    53 #endif
    54     read(k); 
    55     //printf("%d
    ",500-2*k);
    56     int tot=0;
    57     For(n,2*k+1,500) {
    58         tot++;
    59         For(i,1,n) For(j,i+1,n) if(min(abs(i-j),n-abs(i-j))<=k) {
    60             a[i][i]++; 
    61             a[j][j]++;
    62             a[i][j]--;
    63             a[j][i]--; 
    64         }
    65         LL rs=solve(n-1);
    66         printf("%lld,",rs);
    67         For(i,1,n) For(j,1,n) a[i][j]=0;
    68         if(tot==162) break;
    69     }
    70     Formylove;
    71 }
    暴力程序(矩阵树定理)

    对于每个k用上面这个暴力打表,再用下面这个模板得出递推(ps,BM算法n越大越精确,当k=5,n只取到200时会得出90多阶的递推而不是162阶)

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int N=2007,p=65521;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int n,cnt,fail[N];
    20 vector<LL>f[N];
    21 LL a[N],delta[N];
    22 
    23 template<typename T>void read(T &x)  {
    24     char ch=getchar(); x=0; T f=1;
    25     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    26     if(ch=='-') f=-1,ch=getchar();
    27     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    28 }
    29 
    30 LL ksm(LL a,LL b) {
    31     LL rs=1,bs=a%p;
    32     while(b) {
    33         if(b&1) rs=rs*bs%p;
    34         bs=bs*bs%p;
    35         b>>=1;
    36     }
    37     return rs;
    38 }
    39 
    40 #define ANS
    41 int main() {
    42 #ifdef ANS
    43     freopen("biao.out","r",stdin);
    44     freopen("k4.out","w",stdout);
    45 #endif
    46     read(n);
    47     For(i,1,n) read(a[i]);
    48     For(i,1,n) {
    49         LL tp=0;
    50         int up=f[cnt].size();
    51         For(j,0,up-1) 
    52             tp=(tp+f[cnt][j]*a[i-j-1]%p)%p;
    53         if(tp==a[i]) continue;
    54         delta[i]=(a[i]-tp+p)%p;
    55         fail[cnt]=i;
    56         ++cnt;
    57         if(cnt==1) {
    58             f[cnt].resize(i);
    59             continue;
    60         }
    61         LL mul=delta[i]*ksm(delta[fail[cnt-2]],p-2)%p,fmul=(p-mul)%p;
    62         f[cnt].resize(i-fail[cnt-2]-1);
    63         f[cnt].push_back(mul);
    64         up=f[cnt-2].size();
    65         For(j,0,up-1)
    66             f[cnt].push_back(fmul*f[cnt-2][j]%p);
    67         up=f[cnt-1].size();
    68         if(f[cnt].size()<f[cnt-1].size()) f[cnt].resize(up);
    69         For(j,0,up-1) f[cnt][j]=(f[cnt][j]+f[cnt-1][j])%p; 
    70     }
    71     int up=f[cnt].size();
    72     printf("%d
    ",up);
    73     For(i,0,up-1) printf("%lld,",f[cnt][i]);
    74     Formylove;
    75 }
    模意义下BM模板

    把打出来的表直接放程序里,暴力递推就有80了。

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int p=65521;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int len[10]={0,2,6,18,54,162};
    20 LL f[10][200]={{},{0,2,65520},{0,4,0,65511,0,4,65520},{0,4,8,18,65401,65269,65038,72,272,964,272,72,65038,65269,65401,18,8,4,65520},{0,6,15,0,30,62797,60175,64321,63502,7551,27432,56468,63447,45434,59589,49862,56027,40848,38206,22675,8556,3412,32492,56715,38363,45055,20818,27014,20818,45055,38363,56715,32492,3412,8556,22675,38206,40848,56027,49862,59589,45434,63447,56468,27432,7551,63502,64321,60175,62797,30,0,15,6,65520},{0,8,16,65511,304,1112,62517,8818,65348,42675,8648,3411,62664,34224,61359,23789,47033,9577,18774,26446,25242,2440,16835,19355,24778,54491,33418,44673,31664,47318,45699,57034,58329,16947,14821,37483,29701,44701,57248,45494,20917,51056,23909,32660,48089,10311,61927,58068,19461,11155,62649,39025,36755,38928,31565,26603,24094,10349,15499,13713,26713,29605,28753,24627,62639,16313,6983,45353,19779,57391,61923,7930,19732,34243,31283,21822,15252,63919,32152,22840,52349,39683,52349,22840,32152,63919,15252,21822,31283,34243,19732,7930,61923,57391,19779,45353,6983,16313,62639,24627,28753,29605,26713,13713,15499,10349,24094,26603,31565,38928,36755,39025,62649,11155,19461,58068,61927,10311,48089,32660,23909,51056,20917,45494,57248,44701,29701,37483,14821,16947,58329,57034,45699,47318,31664,44673,33418,54491,24778,19355,16835,2440,25242,26446,18774,9577,47033,23789,61359,34224,62664,3411,8648,42675,65348,8818,62517,1112,304,65511,16,8,65520}};
    21 LL a[10][200]={{},{0,3,4},{0,125,384,1183,3528,10404,30250},{0,16807,17423,19038,4069,36749,10890,20559,13383,44811,44978,31152,53478,7585,61903,7694,36892,16182,32848},{0,65457,7500,44205,40188,48640,8405,785,15584,27550,24009,2806,39941,39586,12655,29060,63519,440,55231,44413,1719,61638,15338,1980,42275,50263,4780,56562,5966,13459,65345,34985,7721,23101,124,14839,52885,15175,36581,16396,48404,48035,17828,33918,65101,15000,2860,2388,63410,9605,50082,55806,49163,56598,63631},{0,43464,44962,35706,26874,2031,35703,14530,53646,61395,56708,29157,43858,3788,7056,41580,35556,22057,12105,25313,43903,43174,50192,48518,28112,37197,16270,49973,27582,18340,39356,28374,39671,33552,22814,29972,42427,19919,38723,24057,51493,6507,45387,18936,65511,31659,44915,62932,34532,65492,5505,65280,61430,9555,21382,18222,21311,853,52691,17163,48026,45847,22611,22383,30878,32423,7502,14151,47992,49564,36686,24946,21597,5702,10921,28206,39980,64500,34046,44791,42032,19696,32425,58579,50204,11055,40170,56738,14539,3621,56024,40757,56759,1895,3710,15280,40381,27494,42590,45942,46226,4201,64024,26768,41146,2839,57415,45261,18437,19547,34769,5118,1282,62750,31296,62980,42068,57199,26653,51220,13640,60680,16245,27774,54000,14218,38367,56167,56929,61021,33773,62448,58886,2385,24829,45945,46912,21640,18358,36563,28022,33944,42920,38354,47928,52596,36132,28846,50297,46818,25798,48043,58726,47491,31838,56042,32772,22166,49864,13935,19648,521,63481}};
    22 LL b[10007],n,k;
    23 
    24 template<typename T>void read(T &x)  {
    25     char ch=getchar(); x=0; T f=1;
    26     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    27     if(ch=='-') f=-1,ch=getchar();
    28     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    29 }
    30 
    31 #define ANS
    32 int main() {
    33 #ifdef ANS
    34     freopen("shanghai.in","r",stdin);
    35     freopen("shanghai.out","w",stdout);
    36 #endif
    37     read(k); read(n);
    38     For(i,1,len[k]) b[i+2*k]=a[k][i];
    39     For(i,len[k]+2*k+1,n) {
    40         For(j,1,len[k]) b[i]=(b[i]+f[k][j]*b[i-j]%p)%p;
    41     }
    42     printf("%lld
    ",b[n]);
    43     Formylove;
    44 }
    45 /*
    46 
    47 */
    80pt

    矩乘优化好像跑不过,得多项式取模优化才行。。。

    多项式取模优化k阶常系数线性递推

    时间复杂度k^2logn

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int p=65521;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int len[10]={0,2,6,18,54,162};
    20 LL f[10][200]={{},{0,2,65520},{0,4,0,65511,0,4,65520},{0,4,8,18,65401,65269,65038,72,272,964,272,72,65038,65269,65401,18,8,4,65520},{0,6,15,0,30,62797,60175,64321,63502,7551,27432,56468,63447,45434,59589,49862,56027,40848,38206,22675,8556,3412,32492,56715,38363,45055,20818,27014,20818,45055,38363,56715,32492,3412,8556,22675,38206,40848,56027,49862,59589,45434,63447,56468,27432,7551,63502,64321,60175,62797,30,0,15,6,65520},{0,8,16,65511,304,1112,62517,8818,65348,42675,8648,3411,62664,34224,61359,23789,47033,9577,18774,26446,25242,2440,16835,19355,24778,54491,33418,44673,31664,47318,45699,57034,58329,16947,14821,37483,29701,44701,57248,45494,20917,51056,23909,32660,48089,10311,61927,58068,19461,11155,62649,39025,36755,38928,31565,26603,24094,10349,15499,13713,26713,29605,28753,24627,62639,16313,6983,45353,19779,57391,61923,7930,19732,34243,31283,21822,15252,63919,32152,22840,52349,39683,52349,22840,32152,63919,15252,21822,31283,34243,19732,7930,61923,57391,19779,45353,6983,16313,62639,24627,28753,29605,26713,13713,15499,10349,24094,26603,31565,38928,36755,39025,62649,11155,19461,58068,61927,10311,48089,32660,23909,51056,20917,45494,57248,44701,29701,37483,14821,16947,58329,57034,45699,47318,31664,44673,33418,54491,24778,19355,16835,2440,25242,26446,18774,9577,47033,23789,61359,34224,62664,3411,8648,42675,65348,8818,62517,1112,304,65511,16,8,65520}};
    21 LL a[10][200]={{},{0,3,4},{0,125,384,1183,3528,10404,30250},{0,16807,17423,19038,4069,36749,10890,20559,13383,44811,44978,31152,53478,7585,61903,7694,36892,16182,32848},{0,65457,7500,44205,40188,48640,8405,785,15584,27550,24009,2806,39941,39586,12655,29060,63519,440,55231,44413,1719,61638,15338,1980,42275,50263,4780,56562,5966,13459,65345,34985,7721,23101,124,14839,52885,15175,36581,16396,48404,48035,17828,33918,65101,15000,2860,2388,63410,9605,50082,55806,49163,56598,63631},{0,43464,44962,35706,26874,2031,35703,14530,53646,61395,56708,29157,43858,3788,7056,41580,35556,22057,12105,25313,43903,43174,50192,48518,28112,37197,16270,49973,27582,18340,39356,28374,39671,33552,22814,29972,42427,19919,38723,24057,51493,6507,45387,18936,65511,31659,44915,62932,34532,65492,5505,65280,61430,9555,21382,18222,21311,853,52691,17163,48026,45847,22611,22383,30878,32423,7502,14151,47992,49564,36686,24946,21597,5702,10921,28206,39980,64500,34046,44791,42032,19696,32425,58579,50204,11055,40170,56738,14539,3621,56024,40757,56759,1895,3710,15280,40381,27494,42590,45942,46226,4201,64024,26768,41146,2839,57415,45261,18437,19547,34769,5118,1282,62750,31296,62980,42068,57199,26653,51220,13640,60680,16245,27774,54000,14218,38367,56167,56929,61021,33773,62448,58886,2385,24829,45945,46912,21640,18358,36563,28022,33944,42920,38354,47928,52596,36132,28846,50297,46818,25798,48043,58726,47491,31838,56042,32772,22166,49864,13935,19648,521,63481}};
    22 LL b[10007],n,k;
    23 
    24 template<typename T>void read(T &x)  {
    25     char ch=getchar(); x=0; T f=1;
    26     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    27     if(ch=='-') f=-1,ch=getchar();
    28     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    29 }
    30 
    31 LL rs[507],bs[507];
    32 void mul(LL a[],LL b[],LL c[]) {
    33     static LL tp[507];
    34     int up=(len[k]<<1);
    35     For(i,0,up) tp[i]=0;
    36     For(i,0,len[k]-1) For(j,0,len[k]-1)
    37         (tp[i+j]+=a[i]*b[j]%p)%=p; 
    38     Rep(i,up,len[k]) For(j,1,len[k]) 
    39         (tp[i-j]+=f[k][j]*tp[i]%p)%=p;
    40     For(i,0,up) c[i]=tp[i]; 
    41 }
    42 
    43 void ksm(LL b) {
    44     while(b) {
    45         if(b&1) mul(rs,bs,rs);
    46         mul(bs,bs,bs);
    47         b>>=1;    
    48     }
    49 }
    50 
    51 #define ANS
    52 int main() {
    53 #ifdef ANS
    54     freopen("shanghai.in","r",stdin);
    55     freopen("shanghai.out","w",stdout);
    56 #endif
    57     read(k); read(n);
    58     n-=2*k;
    59     For(i,1,len[k]) b[i]=a[k][i];
    60     if(n<=len[k]) printf("%lld
    ",b[n]);
    61     else {
    62         rs[0]=1; bs[1]=1; 
    63         ksm(n-1);
    64         LL ans=0;
    65         For(i,0,len[k]-1) (ans+=b[i+1]*rs[i]%p)%=p;
    66         printf("%lld
    ",ans);
    67     }
    68     Formylove;
    69 }
    100pt
  • 相关阅读:
    Songbird:一边上网,一边听歌
    利用 Sunbird 处置你的日程表
    Automatix 2 for Ubuntu 6.10
    新的一年,新的起点~~好好干
    Delphi 2009 新增单元 Character[2]: IsLetter、IsUpper、IsLower、IsDigit、IsNumber
    重载 CreateParams 方法[2]: 重载 TForm.CreateParams 方法的几个例子
    实现无标题栏但有边框的窗口
    Delphi 2009 新增单元 Character[1]: ToUpper、ToLower 字符与字符串的大小写转换
    使用 TRegistry 类[4]: 文件打开与文件图标的关联
    ASCII 码新表 包含 Delphi 2009 的 TUnicodeCategory 分类
  • 原文地址:https://www.cnblogs.com/Achenchen/p/9506892.html
Copyright © 2020-2023  润新知