sm 528 T1 && T2

来源:互联网 发布:elvis elvin 知乎 编辑:程序博客网 时间:2024/04/18 18:02

T1:

problem:

给定n个给定长度的木棍,最多可以切maxcut刀,问最多形成多少个长度为10的个棍。


solution:

先从小到大处理长度为10的倍数的木棍,然后处理剩余的木棍,每次切出一个长度为10的木棍直到长度小于等于10。

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;class Cut {public:    int getMaximum(vector <int> eelLengths, int maxCuts) {int n = eelLengths.size();sort(eelLengths.begin(), eelLengths.end());int ans = 0;for (int i = 0; i < n; ++i)     if (eelLengths[i] % 10 == 0) {while (maxCuts > 0 && eelLengths[i] > 10) {    --maxCuts;    eelLengths[i] -= 10;    ++ans;}if (eelLengths[i] == 10) ++ans;    }for (int i = 0; i < n; ++i) {    while (maxCuts > 0 && eelLengths[i] > 10) {--maxCuts;eelLengths[i] -= 10;++ans;    }}return ans;    }};

T2:

problem:

给定一个长度为n(n <= 40)的字符串S(只有‘x,'‘o’)。现要求有多少对集合<X,Y>满足:

X = {p1, p2, p3...., p[n / 2]}, p1 < p2 ...< p [n / 2]

Y = {q1, q2, q3,... q[n / 2]}, q1 < q2 ... < q[n / 2]

X 和 Y的并集为 {1, 2, 3, ..., n}

S[pi] = S[qi] .


solution:

如果 n <= 20,那么可以设 f[i][mask]代表处理完前 i 个字符,元素多的那个集合比少那个的多了mask的元素。如果第i + 1个字符等于mask里的第一个元素所代表的字符,那么可以转移到f[i + 1][mask - p] , p是mask里的第一个元素(相当于把第i + 1个字符加入元素少的集合),或者可以将第i + 1 个字符加入元素多的那个集合,即转移到 f[i + 1][mask  + (i + 1)]。最后的f[n][0]即是答案。

这题的n <= 40, 那么可以将原串拆成两部分做,前半部分要求两个集合的前缀字符要相同,后半部分要求两个集合的后缀字符要相同。所以前半部分和前面的做法一样,而后半部分需要将串先翻转再做。然后就是合并两个串的结果,考虑到前半部分的结果f[n / 2][mask],代表元素多的集合多了mask,所以就要求后半部分要把多的这些填补上去。即对于所有满足mask1 的翻转等于mask的集合,将 f[n / 2][mask] * g[n / 2][mask1]计入答案(g是后半部分的结果)。


#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <map>using namespace std;typedef long long LL;typedef unsigned long long ULL;int a[30], b[30];LL dp[2][1 << 20];LL f1[1 << 20], f2[1 << 20];const int P = 40007;map <ULL, LL> wayss;inline void updata(LL &x, LL y) {    x += y;}inline void solve(int a[], int n, LL f[]) {    memset(dp, 0, sizeof(dp));    int cur = 0, nex = 1;    dp[0][0] = 1;    for (int i = 0; i < n; ++i) {memset(dp[nex], 0, sizeof(dp[nex]));for (int mask = 0; mask < 1 << n; ++mask) {    if (!dp[cur][mask]) continue;    if (mask == 0) updata(dp[nex][1 << i], dp[cur][mask] * 2);    else {int lowbit = mask & -mask;int j = __builtin_ctz(lowbit);if (a[j] == a[i]) updata(dp[nex][mask ^ lowbit], dp[cur][mask]);updata(dp[nex][mask | (1 << i)], dp[cur][mask]);    }}swap(cur, nex);    }    memcpy(f, dp[cur], sizeof(dp[cur]));}class SPartition {public:    LL getCount(string s) {int n = s.size(), m = n / 2;for (int i = 0; i < m; ++i)    a[i] = (s[i] == 'o');for (int i = 0; i < m; ++i)    b[i] = (s[n - i - 1] == 'o');solve(a, m, f1);solve(b, m, f2);for (int i = 0; i < 1 << m; ++i)    f2[i] /= 2;LL ans = f1[0] * f2[0] * 2;for (int mask = 1; mask < 1 << m; ++mask)     if (f2[mask]) {ULL sum = 0;for (int i = m - 1; i >= 0; --i)    if (mask >> i & 1) sum = sum * P + b[i] + 10;wayss[sum] += f2[mask];    }for (int mask = 1; mask < 1 << m; ++mask)     if (f1[mask]) {ULL sum = 0;for (int i = 0; i < m; ++i)    if (mask >> i & 1) sum = sum * P + a[i] + 10;ans += f1[mask] * wayss[sum];    }return ans;    }};


0 0
原创粉丝点击