zoukankan      html  css  js  c++  java
  • 【NOIP2018提高组D2T2】填数游戏

    此题较为特殊,有两种打法
    1.打表过
    2.正解

    打表的:

    #include<bits/stdc++.h>
    using namespace std;
    #define mo 1000000007ll
    typedef long long ll;
    ll n,m,ans1[20],ans2[20];
    ll qp(ll x,ll y){
    	if(!y)return 1;
    	if(y==1)return x%mo;
    	ll r=qp(x,y/2);
    	if(y%2==1)return r*r%mo*x%mo;
    	return r*r%mo;
    }
    //r[n][n]=r[n-1][n-1]*8-5*2^n
    //r[n][n+1]=r[n][n]*3-3*2^n
    int main(){
    	freopen("game.in","r",stdin);
    	freopen("game.out","w",stdout);
    	scanf("%lld%lld",&n,&m);
    	if(n>m)swap(n,m);
    	if(n==1) printf("%lld
    ",qp(2,m));
    	else if(n==2) printf("%lld
    ",4*qp(3,m-1)%mo);
    	else if(n==3) printf("%lld
    ",112*qp(3,m-3)%mo);
    	else
    	{
    		ans1[4]=912;
    		for(ll i=5;i<=10;i++)
    			ans1[i]=(ans1[i-1]*8ll-5ll*qp(2,i)%mo+mo)%mo;
    		for(ll i=4;i<=10;i++)
    			ans2[i]=(ans1[i]*3-3*qp(2,i)%mo+mo)%mo;
    		if(n==m) printf("%lld
    ",ans1[n]);
    		else printf("%lld
    ",ans2[n]*qp(3,m-n-1)%mo);
    	}
    }
    

    正解:

    #include <cstdio>
    
    #define ll long long
    #define F(i, a, b) for (ll i = a; i <= b; i ++)
    #define max(a, b) ((a) > (b) ? (a) : (b))
    #define mx(a, b) ((a) = max(a, b))
    #define add(a, b) ((a) = (a + b) % Mo)
    
    const ll Mo = 1e9 + 7, N = 1e6 + 10, M = 100;
    using namespace std;
    
    ll n, m, ans, ANS1, ANS2, a1, a2, f[N], S[M];
    bool bz, bz1, bz2, bz3; ll all;
    
    ll ksm(ll x, ll y) {
    	ll ans = 1;
    	for (; y; y >>= 1, x = (1LL * x * x) % Mo)
    		if (y & 1)
    			ans = (1LL * ans * x) % Mo;
    	return ans;
    }
    
    void Go(ll now, ll x, ll y) {
    	if (bz) return;
    	if (x == n && y == m) {
    		if (now < all) { bz = 1; return; }
    		mx(all, now); return;
    	}
    	if (y < m) Go(now * 10 + S[(x - 1) * m + y], x, y + 1);
    	if (x < n) Go(now * 10 + S[(x - 1) * m + y], x + 1, y);
    }
    
    void Dfs(ll k) {
    	if (k - 1 > m && (k - 1) % m && S[k - 1] < S[k - m]) return;
    	if (k - 1 > m && S[m + 1] == S[2]) bz1 = 1; else bz1 = 0;
    	if (k - 1 > m + 1 && S[m + 2] == S[3]) bz2 = 1; else bz2 = 0;
    	if (k - 1 > 2 * m && S[2 * m + 1] == S[m + 2]) bz3 = 1; else bz3 = 0;
    	if (bz1 && (k - 1) % m > 1 && k - 1 > 2 * m && S[k - 1] != S[k - m]) return;
    	if (bz2 && (k - 1) % m > 2 && k - 1 > 2 * m && S[k - 1] != S[k - m]) return;
    	if (bz3 && (k - 1) % m > 1 && k - 1 > 3 * m && S[k - 1] != S[k - m]) return;
    	if (k > n * m) {
    		if (S[1] || S[n * m]) return;
    		bz = all = 0, Go(0, 1, 1), ans += !bz;
    		return;
    	}
    	S[k] = 1, Dfs(k + 1);
    	S[k] = 0, Dfs(k + 1);
    }
    
    int main() {
    	freopen("game.in", "r", stdin);
    	freopen("game.out", "w", stdout);
    	scanf("%d%d", &n, &m);
    	if (n > m) n += m, m = n - m, n = n - m;
    	if (n == 1 || n == 2) {
    		printf("%d
    ", n == 1 ? ksm(2, m) : 12 * ksm(3, m - n) % Mo);
    		return 0;
    	}
    	if (n == 3) {
    		printf("%d
    ", 112 * ksm(3, m - n) % Mo);
    		return 0;
    	}
    	if (n * m <= 20) {
    		Dfs(1);
    		printf("%d
    ", ans * 4);
    		return 0;
    	}
    	F(i, 1, n - 4)
    		f[i + 1] = (4 * 5 + f[i] * 4) % Mo; // 4表示上一条对角线第一次成对儿.
    	ans = 2 * (3 + 4 * 3 + f[n - 3] * 2) * ksm(2, n - 1);
    	a1 = ksm(4, n - 2) * ksm(2, n + 1) % Mo;
    	a2 = 5 * ksm(4, n - 4) * ksm(2, n + 1) % Mo;
    	if (n == m) { printf("%d", (ans + a1 + a2) % Mo); return 0; }
    	ANS1 = (4 + 4 * 4 + (f[n - 3] * 3 + 4 * 3) * 2) * ksm(2, n - 1) % Mo;
    	ANS2 = (f[n - 3] * 3 + 4 * 5) * ksm(2, n) % Mo;
    	printf("%d", ((((a1 + a2) * 3 + ANS1 + ANS2) % Mo) * ksm(3, m - n - 1)) % Mo);
    }
    
    转载需注明出处。
  • 相关阅读:
    连接mysql遇到的问题
    洛谷 P3369 【模板】普通平衡树(Treap/SBT)
    开博啦
    luogu【P2753】[USACO4.3]字母游戏Letter Game
    luogu【P3377】 【模板】左偏树
    POJ-2251
    HDU-1518
    Coderforces-455A
    UVA-1608
    Coderfocers-551C
  • 原文地址:https://www.cnblogs.com/jz929/p/11817838.html
Copyright © 2011-2022 走看看