zoukankan      html  css  js  c++  java
  • 【简•解】花园

    【题目描述】

    传送门

    (L)有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为(1)~(N(2le Nle 10^{15}))。他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻(M(2le Mle 5,Mle N))个花圃中有不超过(K(1le K<M))(C)形的花圃,其余花圃均为(P)形的花圃。

    求合法方案数,对模烂的数(1e9+7)取模。

    【分析】

    看到(M)这么小,考虑到状压。

    但看到(N)这么大,那就快速幂吧,此题完。

    【Code】

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define ll long long
    #define debug() puts("FBI WARNING!")
    using namespace std;
    const int P = 19260817;
    const int MOD = 1000000007;
    const int MAX = 300000 + 5; 
    const int M = 5;
    inline ll read(){
    	ll f = 1, x = 0; char ch;
    	do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0' || ch > '9');
    	do {x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    	return f * x;
    }
    
    struct TOOL {
    	#define Hanabi ll
    	inline Hanabi max(Hanabi a, Hanabi b) { return a < b ? b : a; }
    	inline Hanabi min(Hanabi a, Hanabi b) { return a < b ? a : b; }
    	inline Hanabi abs(Hanabi a) { return a < 0 ? a : a; }
    }t;
    
    int m, K, jd[1 << M], limit, cover;
    ll n, f[1 << M], vis[1 << M][1 << M], ans;
    
    inline void mul() {
    	ll c[1 << M];
    	memset(c, 0, sizeof c);
    	for (int j = 0;j < limit; ++j) {
    		for (int k = 0;k < limit; ++k) {
    			c[j] = (c[j] + f[k] * vis[k][j]) % MOD;
    		}
    	}
    	memmove(f, c, sizeof c);
    }
    
    inline void mulself() {
    	ll c[1 << M][1 << M];
    	memset(c, 0, sizeof c);
    	for (int i = 0;i < limit; ++i) {
    		for (int j = 0;j < limit; ++j) {
    			for (int k = 0;k < limit; ++k) {
    				c[i][j] = (c[i][j] + vis[i][k] * vis[k][j]) % MOD;
    			}
    		}
    	}
    	memmove(vis, c, sizeof c);
    }
    
    int main(){
    	n = read(), m = read(), K = read();
    	limit = 1 << m;
    	cover = (1 << (m - 1)) - 1;
    	for (int i = 0;i < limit; ++i) {
    		int cnt = 0;
    		for (int j = 0;j < m; ++j) {
    			if (i & (1 << j)) ++cnt;
    		}
    		if (cnt <= K) jd[i] = 1;
    	}
    	
    	for (int i = 0;i < limit; ++i) {
    		if (jd[i] == 0) continue;
    		memset(f, 0, sizeof f);
    		f[i] = 1;
    		memset(vis, 0, sizeof vis);
    		for (int j = 0;j < limit; ++j) {
    			if (jd[j] && jd[(j & cover) << 1]) vis[j][(j & cover) << 1] = 1;
    			if (jd[j] && jd[((j & cover) << 1) | 1]) vis[j][((j & cover) << 1) | 1] = 1;			
    		}
    		ll x = n;
    		while (x) {
    			if (x & 1) mul();
    			mulself();
    			x >>= 1;
    		}
    		ans = (ans + f[i]) % MOD;
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    一行代码更改博客园皮肤
    fatal: refusing to merge unrelated histories
    使用 netcat 传输大文件
    linux 命令后台运行
    .net core 使用 Nlog 配置文件
    .net core 使用 Nlog 集成 exceptionless 配置文件
    Mysql不同字符串格式的连表查询
    Mongodb between 时间范围
    VS Code 使用 Debugger for Chrome 调试vue
    css权重说明
  • 原文地址:https://www.cnblogs.com/silentEAG/p/11426625.html
Copyright © 2011-2022 走看看