srm 534

250


Description

給你一個1*n的棋盤,兩人輪流行動,每個人可以把”o”向右移動到空格子,或者跨越連續兩個”o”到空格子。一個”o”到最右端的時候消失。問誰獲勝。

Solution

一個比較有趣的題,我們考慮每個”o”到最右端的距離,兩種行動其實都是改變距離的奇偶,所以其實只需要考慮最終狀態和距離和的奇偶性即可。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int d[(1 << N) + 10];
class EllysCheckers {
    public:
    string getWinner(string board) {
        int n = board.size();
        int t = 0;
        for (int i = 0; i < n; ++i) {
            if (board[i] == 'o')    t += n - i - 1;
        }
        return t & 1 ? "YES" : "NO";
    }
};

500



Description:

求把一個n(n1018) 數分解成幾個給定的數組中的幾個數的乘積形式的方案數,要求從給定數組中選出的數要兩兩互質。

Solution

很容易反應到,由於2×3×...×43>1018 ,所以其實n 會被分解成不超過15個質數,且每個質數對應的數組中的數只有一個,就可以狀壓dp了。
也可以直接用map來dp,可以證明,狀態數不會太多。

Code:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
int p[20];
const int N = 505;
LL a[N];
vector<int> b;
map<LL, LL> dp;
map<LL, LL>:: iterator it;
class EllysNumbers {
    public:
        long long getSubsets(long long n, vector <string> special) {
            string s = accumulate(special.begin(), special.end(), string());
            istringstream ss(s);
            int m = 0, x;
            while (ss >> x) a[m++] = x;
            for (int i = 0; i < m; ++i)
                if (__gcd(a[i], n / a[i]) == 1) b.pb(a[i]);
            dp[n] = 1;
            for (int i = 0; i < b.size(); ++i)
                for (it = dp.begin(); it != dp.end(); it++)
                    if (it -> F % b[i] == 0) {
                        dp[it -> F / b[i]] += it -> S;
                    }
            return dp[1];
        }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章