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

非常easy反应到,因为 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];
        }
};

你可能感兴趣的:(srm 534)