• [CodeForces 300D Painting Square]DP


    http://codeforces.com/problemset/problem/300/D

    题意:每一次操作可以选一个正方形,令边长为n,如果n为奇数那么可以从中间画一个十字,分成4个大小相等的边长为(n-1)/2的正方形。给一个正方形,求操作k次后能得到的不同图案的个数

    思路:令f(s,k)表示边长为s的正方形操作k次后的答案总数,则f(s,k)=∑f(s/2,k1)*f(s/2,k2)*f(s/2,k3)*f(s/2,k4),其中s为奇数,k1+k2+k3+k4=k-1,令g(s,k)=Σf(s,k1)*f(s,k2),其中s为奇数,k1+k2=k。那么有f(s,k)=Σg(s/2,k')*g(s/2,k-1-k'),g(s,k)=Σf(s,k')*f(s,k-k'),其中s为奇数,k'取遍所有可能的值。由于s最多递归logs层,所以用一个不超过logs的数和k表示状态即可,然后递推计算,复杂度O(k2logs)

    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define copy(a, b)          memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    //#ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    //#endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    template<typename T>
    void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}
    template<typename T>
    void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}
    
    const double PI = acos(-1.0);
    const int INF = 1e9 + 7;
    const double EPS = 1e-8;
    
    /* -------------------------------------------------------------------------------- */
    
    template<int mod>
    struct ModInt {
        const static int MD = mod;
        int x;
        ModInt(ll x = 0): x(x % MD) {}
        int get() { return x; }
    
        ModInt operator + (const ModInt &that) const { int x0 = x + that.x; return ModInt(x0 < MD? x0 : x0 - MD); }
        ModInt operator - (const ModInt &that) const { int x0 = x - that.x; return ModInt(x0 < MD? x0 + MD : x0); }
        ModInt operator * (const ModInt &that) const { return ModInt((long long)x * that.x % MD); }
        ModInt operator / (const ModInt &that) const { return *this * that.inverse(); }
    
        ModInt operator += (const ModInt &that) { x += that.x; if (x >= MD) x -= MD; }
        ModInt operator -= (const ModInt &that) { x -= that.x; if (x < 0) x += MD; }
        ModInt operator *= (const ModInt &that) { x = (long long)x * that.x % MD; }
        ModInt operator /= (const ModInt &that) { *this = *this / that; }
    
        ModInt inverse() const {
            int a = x, b = MD, u = 1, v = 0;
            while(b) {
                int t = a / b;
                a -= t * b; std::swap(a, b);
                u -= t * v; std::swap(u, v);
            }
            if(u < 0) u += MD;
            return u;
        }
    
    };
    typedef ModInt<7340033> mint;
    
    mint dp[31][1010], f[31][1010];
    
    void pre_init() {
        for (int i = 1; i <= 30; i ++) dp[i][0] = f[i][0] = 1;
        for (int i = 2; i <= 30; i ++) {
            dp[i][1] = 1;
            f[i][1] = 2;
            for (int j = 2; j <= 1000; j ++) {
                for (int k = 0; k <= j; k ++) {
                    dp[i][j] += f[i - 1][k] * f[i - 1][j - k - 1];
                }
                for (int k = 0; k <= j; k ++) {
                    f[i][j] += dp[i][k] * dp[i][j - k];
                }
            }
        }
    }
    
    int work(int n, int k) {
        if (k == 0) return 1;
        int p = 0;
        while (n & 1) {
            p ++;
            n = (n - 1) / 2;
        }
        if (n) p ++;
        return dp[p][k].get();
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n, T, k;
        pre_init();
        while (cin >> T) {
            while (T --) {
                scanf("%d%d", &n, &k);
                printf("%d
    ", work(n, k));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    windows下面Nginx日志切割
    C#通过DocX创建word
    leetcode 189 Rotate Array
    leetcode 172 Factorial Trailing Zeroes
    leetcode 169 Majority Element 冰山查询
    leetcode 165 Compare Version Numbers
    leetcode 160 Intersection of Two Linked Lists
    【windows-》linux】SCP
    【设计】B端和C端区别
    【Flask】部署
  • 原文地址:https://www.cnblogs.com/jklongint/p/4726319.html
Copyright © 2020-2023  润新知