[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
原文地址:https://www.cnblogs.com/Achenchen/p/9506892.html