bzoj1494: [NOI2007]生成树计数
被自己的码力低哭了。
为什么现在随便写个什么一百出头行的并不难写的代码就调一晚上。我大概是个智障吧。
人类进化还不完全的时候的做法:
状压最后k个点的联通状态,矩阵转移,快速幂优化即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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,power[10],zt[10007],S[60];
20 LL n;
21
22 template<typename T>void read(T &x) {
23 char ch=getchar(); x=0; T f=1;
24 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
25 if(ch=='-') f=-1,ch=getchar();
26 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
27 }
28
29 int e[12][2],fa[12],bl[12],tot,ec;
30 int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); }
31
32 LL f[60];
33 struct jz {
34 LL a[60][60];
35 friend jz operator *(const jz&A,const jz&B) {
36 jz rs;
37 For(i,1,tot) For(j,1,tot) {
38 rs.a[i][j]=0;
39 For(k,1,tot)
40 (rs.a[i][j]+=A.a[i][k]*B.a[k][j]%p)%=p;
41 }
42 return rs;
43 }
44 }bs,rs;
45
46 void jzksm(LL b) {
47 For(i,1,tot) For(j,1,tot)
48 if(i==j) rs.a[i][j]=1;
49 else rs.a[i][j]=0;
50 while(b) {
51 if(b&1) rs=rs*bs;
52 bs=bs*bs;
53 b>>=1;
54 }
55 }
56
57 int ansst;
58 void find_begin() {
59 For(i,1,k) For(j,i+1,k) {
60 e[++ec][0]=i;
61 e[ec][1]=j;
62 }
63 int up=(1<<ec)-1;
64 For(s,0,up) {
65 int fl=0;
66 For(i,1,k) fa[i]=i;
67 For(i,0,ec) if(s&(1<<(i-1))) {
68 int u=e[i][0],v=e[i][1];
69 int x=find(u),y=find(v);
70 if(x>y) swap(x,y);
71 if(find(u)==find(v)) { fl=1; break; }
72 fa[y]=x;
73 }
74 if(fl) continue;
75 int id=0,now=0;
76 For(i,1,k) {
77 if(find(i)==i) bl[i]=id++;
78 else bl[i]=bl[find(i)];
79 now=now+bl[i]*power[i-1];
80 }
81 if(!zt[now]) { zt[now]=++tot; S[tot]=now; }
82 f[zt[now]]++;
83 if(now==0)
84 ansst=zt[now];
85 }
86 }
87
88 int nowbl[12],tbl[12];
89 void find_tans() {
90 int up=(1<<k)-1;
91 For(ss,1,tot) {
92 int now=S[ss],fl=0;
93 For(i,1,k) {
94 bl[i]=now%k; tbl[i]=bl[i];
95 if(i!=1&&bl[i]==bl[1]) fl=1;
96 now/=k;
97 }
98 For(i,0,up) {
99 if(!fl&&!(i&1)) continue ;
100 For(j,1,k) bl[j]=tbl[j];
101 int fll=0;
102 For(a,1,k) For(b,a+1,k) if((i&(1<<(a-1)))&&(i&(1<<(b-1)))) {
103 if(bl[a]==bl[b]) { fll=1; break; }
104 }
105 if(fll) continue;
106 bl[k+1]=k+1;
107 int id=0,now=0;
108 For(a,1,k) if((i&(1<<(a-1)))) {
109 For(b,1,k) if(b!=a&&bl[b]==bl[a]) bl[b]=k+1;
110 bl[a]=k+1;
111 }
112 For(ii,2,k+1) For(j,2,k+1) if(bl[j]==bl[ii]) {
113 if(ii==j) nowbl[ii]=id++;
114 else nowbl[ii]=nowbl[j];
115 now=now+power[ii-2]*nowbl[ii];
116 break;
117 }
118 bs.a[ss][zt[now]]++;
119 }
120 }
121 }
122
123 //#define ANS
124 int main() {
125 #ifdef ANS
126 freopen("1.in","r",stdin);
127 freopen("1.out","w",stdout);
128 #endif
129 read(k); read(n);
130 power[0]=1;
131 For(i,1,k) power[i]=power[i-1]*k;
132 find_begin();
133 find_tans();
134 jzksm(n-k);
135 LL ans=0;
136 For(i,1,tot)
137 ans=(ans+f[i]*rs.a[i][ansst]%p)%p;
138 printf("%lld\n",ans);
139 Formylove;
140 }
人类进化完全一些之后,可以用BM算法求出递推式,然后矩乘或者多项式取模来做。
虽然我并不会。
毕竟我还处于元谋人阶段。