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;
    }
    
  • 相关阅读:
    latex
    anaconda
    git stash
    YOLO训练Pedestrain
    OpenCL C
    OpenCL
    OpenVX
    caffe源码阅读
    居住证积分查询地址
    jdk 1.8内存逐步增大的一个bug
  • 原文地址:https://www.cnblogs.com/silentEAG/p/11426625.html
Copyright © 2011-2022 走看看