zoukankan      html  css  js  c++  java
  • TC SRM 701【杂题】

    PartisanGame

    给定 (n) 个石子和两个正整数集合 (A,B),Alice、Bob 轮流操作,Alice 先手,每次可以取对应集合内的正整数个石子,不能操作的人输,求谁获胜。

    (nle 10^9)(A,Bsubseteq{1,2,3,4,5})


    题解告诉我们直接找循环节即可。

    #include<vector>
    #include<string>
    using namespace std;
    typedef vector<int> VI;
    class PartisanGame {
    	static const int N = 5000;
    	bool a[N], b[N];
    	int buc[1024];
    public:
    	string getWinner(int n, VI A, VI B){
    		memset(buc, 0, sizeof buc);
    		a[0] = b[0] = 0;
    		for(int i = 1;i <= n;++ i){
    			a[i] = b[i] = 0;
    			for(int j : A) a[i] |= i >= j && !b[i-j];
    			for(int j : B) b[i] |= i >= j && !a[i-j];
    			if(i < 5) continue;
    			int msk = 0;
    			for(int j = 0;j < 5;++ j)
    				msk = msk<<2 | a[i-j]<<1 | b[i-j];
    			if(buc[msk]){
    				int len = i - buc[msk];
    				n = i + (n-i) % len;
    			} else buc[msk] = i;
    		}
    		return a[n] ? "Alice" : "Bob";
    	}
    };
    

    KthStringAgain

    给定小写字符串 (s),按如下方式给定大小为 (2^{|s|}) 的可重字符串集合:

    start with an empty collection
    for each subset X of the set {1,2,...,|s|}:
        take a new string t and initialize it to the given string s
        for i = 1,2,...,|s|:
            if X contains i:
                reverse the last i characters of t
        add the string t to the collection
    

    求字典序第 (k) 小的字符串。

    (|s|le 50)(1le kle 2^{|s|})


    倒着考虑这个过程,如果没有翻长为 (|s|) 的后缀,(s_1) 仍在开头,否则 (s_1) 在结尾,(s[2:n]) 翻到了前面,同样可以类似地考虑 (s_2,s_3,cdots),所以这个过程相当于维护两个 stack,按顺序 push (s_1,s_2,cdots,s_n),然后拼起来。

    这就可以方便地按位贪心了,复杂度 (O(|s|^3|Sigma|))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    class KthStringAgain {
    	static const int N = 51;
    	int n; string S;
    	LL f[N][N];
    	LL calc(const string &T){
    		int m = T.size(); LL res = 0;
    		memset(f, 0, sizeof f); f[0][0] = 1;
    		for(int i = 0;i < n;++ i)
    			for(int j = 0;j <= i;++ j){
    				if(j >= m || S[i] == T[j]) f[i+1][j+1] += f[i][j];
    				int t = n-1-i+j;
    				if(t >= m || S[i] == T[t]) f[i+1][j] += f[i][j];
    			}
    		for(int i = 0;i <= n;++ i) res += f[n][i];
    		return res;
    	}
    public:
    	string getKth(string S, LL k){
    		n = S.size(); this->S = S;
    		string res;
    		for(int i = 0;i < n;++ i)
    			for(char j = 'a';j <= 'z';++ j){
    				LL tmp = calc(res+j);
    				if(k > tmp) k -= tmp;
    				else {res += j; break;}
    			}
    		return res;
    	}
    };
    

    FibonacciStringSum

    定义没有相邻 1 的 01 串是 Fib 串。

    给定正整数 (n) 和自然数 (a,b),定义 01 串 (s) 的权值是 (x^ay^b),其中 (x,y) 分别是 (s)(0,1) 的个数。

    求所有长为 (n) 的 Fib 串的权值之和(mod(10^9+7))

    (nle 10^9)(a,ble 25)


    首先把 (x^ay^b) 按第二类斯特林数展开成组合数,得到一个线性递推的 dp。

    直接矩阵乘法不太行,但因为这个矩阵比较稀疏,用 BM 算法求出线性递推式即可。

    复杂度 (O(K^2log n))(K) 是递推式阶数,不知道为什么实际上非常小,只有 (100) 左右。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 222, mod = 1e9+7;
    void qmo(int &x){x += x >> 31 & mod;}
    template<typename T>
    bool chmin(T &a, const T &b){if(a > b) return a = b, 1; return 0;}
    int ksm(int a, int b){
    	int r = 1;
    	for(;b;b >>= 1, a = (LL)a * a % mod)
    		if(b & 1) r = (LL)r * a % mod;
    	return r;
    }
    class FibonacciStringSum {
    	int S[26][26], dp[N][26][26], x[N], dt[N], fa[N], cnt, f[N], bs[30][N], K;
    	vector<int> R[N];
    	void mul(int *a, int *b, int *c){
    		static int res[N];
    		memset(res, 0, sizeof res);
    		for(int i = 0;i < K;++ i)
    			for(int j = 0;j < K;++ j)
    				res[i+j] = (res[i+j] + (LL)a[i]*b[j]) % mod;
    		for(int i = (K-1<<1);i >= K;-- i){
    			for(int j = 0;j < K;++ j) res[i-j-1] = (res[i-j-1] + (LL)res[i]*R[cnt][j]) % mod;
    			res[i] = 0;
    		} memcpy(c, res, K<<2);
    	}
    public:
    	int get(int n, int a, int b){
    		memset(dp, 0, sizeof dp);
    		memset(x, 0, sizeof x);
    		memset(dt, 0, sizeof dt);
    		memset(fa, 0, sizeof fa);
    		memset(f, 0, sizeof f);
    		memset(bs, 0, sizeof bs);
    		cnt = 0; S[0][0] = 1;
    		for(int i = 1;i < 26;++ i)
    			for(int j = 1;j <= i;++ j)
    				S[i][j] = ((LL)S[i-1][j]+S[i-1][j-1])*j % mod;
    		dp[0][0][0] = dp[1][0][1] = dp[1][1][0] = 1; dp[1][0][0] = 2;
    		x[0] = !(a||b); x[1] = !a+!b;
    		for(int i = 2;i < N;++ i)
    			for(int j = 0;j <= a;++ j)
    				for(int k = 0;k <= b;++ k){
    					qmo(dp[i][j][k] = dp[i-1][j][k] + dp[i-2][j][k] - mod);
    					if(j){
    						qmo(dp[i][j][k] += dp[i-1][j-1][k] - mod);
    						qmo(dp[i][j][k] += dp[i-2][j-1][k] - mod);
    						if(k) qmo(dp[i][j][k] += dp[i-2][j-1][k-1] - mod);
    					}
    					if(k) qmo(dp[i][j][k] += dp[i-2][j][k-1] - mod);
    					x[i] = (x[i] + (LL)dp[i][j][k]*S[a][j]%mod*S[b][k]) % mod;
    				}
    		for(int i = 0;i < N;++ i){
    			if(!cnt){
    				if(x[i]){
    					fa[0] = i; dt[i] = x[i];
    					R[++cnt].resize(i+1);
    				} continue;
    			}
    			int m = R[cnt].size();
    			dt[i] = x[i]; fa[cnt] = i;
    			for(int j = 0;j < m;++ j)
    				qmo(dt[i] -= (LL)x[i-j-1]*R[cnt][j]%mod);
    			if(!dt[i]) continue;
    			int id = cnt-1, len = i-fa[id]+R[id].size();
    			for(int j = 0;j < cnt-1;++ j)
    				if(chmin(len, i-fa[j]+(int)R[j].size())) id = j;
    			int tmp = (LL)dt[i]*ksm(dt[fa[id]],mod-2) % mod;
    			R[cnt+1] = R[cnt];
    			if(R[cnt+1].size() < len) R[cnt+1].resize(len);
    			qmo(R[cnt+1][i-fa[id]-1] += tmp - mod);
    			for(int j = 0;j < R[id].size();++ j)
    				qmo(R[cnt+1][i-fa[id]+j] -= (LL)tmp*R[id][j]%mod);
    			++cnt;
    		}
    		K = R[cnt].size();
    		bs[0][1] = f[0] = 1;
    		for(int i = 0;i < 29;++ i) mul(bs[i], bs[i], bs[i+1]);
    		for(int i = 29;~i;-- i) if(n>>i&1) mul(f, bs[i], f);
    		int ans = 0;
    		for(int i = 0;i < K;++ i) ans = (ans + (LL)f[i]*x[i]) % mod;
    		return ans;
    	}
    };
    
  • 相关阅读:
    Atitit.播放系统规划新版本 v4 q18 and 最近版本回顾
    Atitit.播放系统规划新版本 v4 q18 and 最近版本回顾
    atitit.极光消息推送服务器端开发实现推送  jpush v3. 总结o7p
    atitit.极光消息推送服务器端开发实现推送  jpush v3. 总结o7p
    Atitit.文件搜索工具 attilax 总结
    Atitit.文件搜索工具 attilax 总结
    Atitit.软件命名空间  包的命名统计 及命名表(2000个名称) 方案java package
    Atitit.软件命名空间  包的命名统计 及命名表(2000个名称) 方案java package
    Atitit..状态机与词法分析  通用分词器 分词引擎的设计与实现 attilax总结
    Atitit..状态机与词法分析  通用分词器 分词引擎的设计与实现 attilax总结
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/15013824.html
Copyright © 2011-2022 走看看