zoukankan      html  css  js  c++  java
  • 「THUSCH 2017」如果奇迹有颜色(burnside引理+状压dp+打表+BM+常系数齐次线性递推)

    https://loj.ac/problem/2981

    这真TM是个防AK题。

    考虑先套上burnside,枚举置换(i),发现问题变成(gcd(i,n))长的环,染m种颜色,连续m个不会出现m个颜色的方案数,记(f(d))表示长为d的环的方案数,则(Ans=sum_{d|n}f(d)*phi(n/d))

    现在就是怎么求一个(f(n))的问题了。

    暴力:

    状态压缩dp,记(dp[i][S])表示确定了前(i)个,第(i-m+2)(i)个颜色状态是(S),的方案数。

    至于环的限制,只要(n)步之后(S)等于一开始的(S)就好了。

    用矩阵乘法优化,时间复杂度:((m^{m-1})^3*log~n)

    可以通过(m<=4)的数据获得55分。

    BM:

    (m)确定时,(f[n])肯定是一个有递推式的序列,且由上一个dp知道递推式长度(le m^{m-1})

    这样就可以BM后常系数齐次线性递推。

    那么问题就是怎么快速算(f[1..n])

    考虑不用矩阵乘法,直接dp:
    先枚举一个(w),表示前(w)个的颜色是(1,2,3,...,w),第(w+1)个颜色(in[1,w])

    然后用刚才那个(dp[i][S]),在(n-w)步后,看看(S)和前w个是否冲突,不冲突,则(f[n]+=dp[n-w][S]*P_m^w)

    这样算(f[1..n])的复杂度是(O(n*(m^{m-1})*m^2))(m=7,n=1000)大概要算20s,本地算出,打表即可。

    接着跑BM,实际上,当(m=7)时,递推式长度也才(410)

    这样就不用多项式取模,直接暴力取模的常系数齐次线性递推即可。

    代码(打表后的BM和递推):https://loj.ac/submission/782204

    代码(打表程序):

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 1e9 + 7;
    
    ll ksm(ll x, ll y) {
    	ll s = 1;
    	for(; y; y /= 2, x = x * x % mo)
    		if(y & 1) s = s * x % mo;
    	return s;
    }
    
    const int M = 117649;
    
    int n, m, t, am[8];
    
    
    int bz[M][8], to[M][8];
    
    namespace sub1 {
    	int cx[10];
    	void build1() {
    		ff(i, 0, t)	{
    			ff(j, 0, m) {
    				ff(k, 0, m) cx[k] = 0; cx[j] = 1;
    				ff(k, 0, m - 1) cx[i / am[k] % m] = 1;
    				int ky = 0;
    				ff(k, 0, m) if(!cx[k]) ky = 1;
    				bz[i][j] = ky;
    				if(ky) to[i][j] = (i / m) + j * am[m - 2];
    			}
    		}
    	}
    }
    	
    
    int po[M][8];
    
    namespace sub2 {
    	int c[20], cx[10];
    	int pd(int n) {
    		fo(i, 1, n - m + 1) {
    			fo(j, 0, m - 1) cx[j] = 0;
    			fo(j, 0, m - 1) cx[c[i + j]] = 1;
    			int ky = 0;
    			fo(j ,0, m - 1) if(!cx[j]) ky = 1;
    			if(!ky) return 0;
    		}
    		return 1;
    	}
    	void build2() {
    		ff(s, 0, am[m - 1]) {
    			fo(i, 1, m - 1) c[i] = s / am[i - 1] % m;
    			fo(w, 1, m - 1) {
    				fo(j, m, m + w - 1) c[j] = j - m;;
    				po[s][w] = pd(m + w - 1);
    			}
    		}
    	}
    }
    
    ll fac[10], nf[10];
    ll P(int n, int m) { return fac[n] * nf[n - m] % mo;}
    
    ll a[2005], f[2][M], o;
    
    int main() {
    	freopen("a.out", "w", stdout);
    	for(m = 0; m <= 7; m ++) {
    		fo(i, 0, 1000) a[i] = 0;
    		am[0] = 1; fo(i, 1, m) am[i] = am[i - 1] * m;
    		t = am[m - 1];
    		sub1 :: build1();
    		sub2 :: build2();
    		fo(i, 0, m - 1) a[i] = ksm(m, i);
    		fac[0] = 1; fo(i, 1, m) fac[i] = fac[i - 1] * i;
    		fo(i, 0, m) nf[i] = ksm(fac[i], mo - 2);
    		fo(w, 1, m - 1) {
    			memset(f, 0, sizeof f);
    			int st = 0;
    			fo(i, 0, w - 1) st += am[(m - 1 - w) + i] * i;
    			f[o][st] = 1;
    			fo(p, w + 1, 1000) {
    				memset(f[!o], 0, sizeof f[!o]);
    				ff(i, 0, t) if(f[o][i]) {
    					fo(j, 0, (p == w + 1 ? w - 1 : m - 1)) if(bz[i][j]) {
    						f[!o][to[i][j]] = (f[!o][to[i][j]] + f[o][i]) % mo;
    					}
    				}
    				o = !o;
    				if(p >= m) {
    					ff(i, 0, t) if(po[i][w]) {
    						a[p] = (a[p] + P(m, w) * f[o][i]) % mo;
    					}
    				}
    			}
    		}
    		pp("{");
    		fo(i, 0, 1000) {
    			pp("%lld", a[i]);
    			if(i != 1000) pp(",");
    		}
    		pp("},");
    		hh;
    //		fo(i, 1, 100) pp("%lld ", a[i]);
    	}
    	
    }
    
  • 相关阅读:
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(2)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(10)
    CKEditor在asp.net环境下的使用一例
    《Microsoft Sql server 2008 Internals》读书笔记第五章Table(7)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(11)
    千万数据的连续ID表,快速读取其中指定的某1000条数据?
    javascript中的float运算精度
    .Net与Java的互操作(.NET StockTrader微软官方示例应用程序)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(6)
  • 原文地址:https://www.cnblogs.com/coldchair/p/12649680.html
Copyright © 2011-2022 走看看