• 【BZOJ 1494】【NOI 2007】生成树计数


    http://www.lydsy.com/JudgeOnline/problem.php?id=1494
    这道题。。因为k很小,而且我们只关心连续的k个节点的连通性,所以把连续的k个点轮廓线上的连通性的最小表示当做状态来转移。
    转移可以构造一个矩阵,构造矩阵不难想,但挺麻烦的。。。
    时间复杂度(O(Mlen2^kk^2+Mlen^3logn)),Mlen最坏情况下为52。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    const ui p = 65521;
    
    ui ipow(ui a, ui b) {
    	ui t = 1, w = a;
    	while (b) {
    		if (b & 1) t = (t * w) % p;
    		w = (w * w) % p;
    		b >>= 1;
    	}
    	return t;
    }
    
    int k;
    ll n;
    
    struct data {
    	int a[5];
    } state[53];
    
    int cnt[5], tot = 0, max_now, bi[5], ref[1000003];
    ui f[53], ret, rr;
    
    void checkmin(int num) {
    	rr = num;
    	for (int i = 0; i < k; ++i) {
    		bi[i] = num % 10;
    		if (bi[i] >= k) return;
    		num /= 10;
    	}
    	
    	max_now = -1;
    	for (int i = 0; i < k; ++i)
    		if (bi[i] > max_now + 1) return;
    		else max_now = max(max_now, bi[i]);
    	
    	++tot; memset(cnt, 0, sizeof(cnt)); ref[rr] = tot;
    	for (int i = 0; i < k; ++i)
    		state[tot].a[i] = bi[i], ++cnt[bi[i]];
    	ret = 1;
    	for (int i = 0; i < k; ++i)
    		if (cnt[i] > 1)
    			ret = ret * ipow(cnt[i], cnt[i] - 2) % p;
    	f[tot] = ret;
    }
    
    struct Matrix {
    	ui a[53][53];
    	Matrix() {memset(a, 0, sizeof(a));}
    } W, T;
    
    Matrix operator * (Matrix A, Matrix B) {
    	Matrix C;
    	for (int k = 1; k <= tot; ++k)
    		for (int i = 1; i <= tot; ++i)
    			for (int j = 1; j <= tot; ++j)
    				C.a[i][j] = (C.a[i][j] + (A.a[i][k] * B.a[k][j] % p)) % p;
    	return C;
    }
    
    bool flag, vis[100003];
    int col[5], ora[5];
    
    void mark_matrix(int row, int *pre) {
    	flag = true; max_now = 0;
    	for (int i = 1; i < k; ++i) {
    		max_now = max(max_now, pre[i]);
    		if (pre[i] == pre[0])
    			flag = false;
    	}
    	
    	int totnum = (1 << (max_now + 1)), mark, lalala, now;
    	ret = 0;
    	for (int i = 0; i < totnum; ++i) {
    		if (flag && (i & 1) == 0) continue;
    		mark = -1;
    		for (int j = 0; j < k; ++j) col[j] = j;
    		for (int j = 0; j <= max_now; ++j)
    			if ((1 << j) & i) {
    				if (mark == -1) mark = j;
    				else col[j] = mark;
    			}
    		
    		memset(ora, -1, sizeof(ora)); lalala = -1;
    		for (int j = 1; j < k; ++j)
    			if (ora[col[pre[j]]] == -1)	bi[j - 1] = (ora[col[pre[j]]] = ++lalala);
    			else bi[j - 1] = ora[col[pre[j]]];
    		
    		if (mark != -1 && ora[mark] != -1) bi[k - 1] = ora[mark];
    		else bi[k - 1] = ++lalala;
    		
    		now = bi[k - 1];
    		for (int j = k - 2; j >= 0; --j) now = now * 10 + bi[j];
    		if (!ref[now]) continue;
    		ret = 1;
    		if (mark != -1)
    			for (int j = 0; j < k; ++j)
    				if (col[j] == mark) {
    					rr = 0;
    					for (int l = 0; l < k; ++l)
    						if (pre[l] == j) ++rr;
    					ret = ret * rr % p;
    				}
    		
    		W.a[row][ref[now]] = ret;
    	}
    }
    
    int main() {
    	scanf("%d%lld", &k, &n);
    	
    	if (k >= n) {printf("%u
    ", ipow(n, n - 2)); return 0;}
    	
    	int bas = 1; for (int i = 1; i <= k; ++i) bas = bas * 10;
    	for (int i = 0; i <= 43210; ++i)
    		if (!vis[i % bas])
    			checkmin(i), vis[i % bas] = true;
    	
    	n -= k;
    	for (int i = 1; i <= tot; ++i)
    		mark_matrix(i, state[i].a);
    	
    /*	for (int i = 1; i <= tot; ++i) {
    		for (int j = 1; j <= tot; ++j)
    			printf("%d ", W.a[i][j]);
    		puts("");
    	}*/
    	
    	for (int i = 1; i <= tot; ++i)
    		T.a[i][i] = 1;
    	
    	while (n) {
    		if (n & 1) T = W * T;
    		W = W * W;
    		n >>= 1;
    	}
    	
    /*	puts("");
    	for (int i = 1; i <= tot; ++i) {
    		for (int j = 1; j <= tot; ++j)
    			printf("%d ", T.a[i][j]);
    		puts("");
    	}*/
    	
    	ui ans = 0;
    	for (int i = 1; i <= tot; ++i)
    		ans = (ans + f[i] * T.a[i][1] % p) % p;
    	printf("%u
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    外媒评出的中国最美的地方
    外媒评出的中国最美的地方
    中国十大徒步路线,你走过几个?
    中国十大徒步路线,你走过几个?
    还在用Ghost?Windows 7时代用True Image了
    查看手机已经记住的WIFI密码
    查看手机已经记住的WIFI密码
    量子力学的经典教材
    量子力学的经典教材
    索尼全画幅微单A7/A7R上市
  • 原文地址:https://www.cnblogs.com/abclzr/p/6145543.html
Copyright © 2020-2023  润新知