problem1 link

定义一个字符串s,定义函数$f(s)=\sum_{i=1}^{i<|s|}[s_{i-1}\neq s_{i}]$,给定字符串$p,q$,定义函数$g(p,q)=\sum_{c='a'}^{c<='z'}count(p,c)*count(q,c)$。其中 $count(s,c)$表示字符$c$在$s$中出现的次数。给定整数N,构造一个包含N个字符串的集合$S$,每个字符串仅有小写字母构成且每个字符串长度不超过100,使得$S$满足$\sum_{s\in S}f(s)=\sum_{p,q\in S \wedge p\neq q}g(p,q)$。右侧计算了$\frac{N(N-1)}{2}$对串的$g$值。

假定由w,x,y,z组成的串的长度都是1,那么他们只对$g$有贡献,而剩下的字符每两个构成一个串,且任意两个串不使用同一个字符,那么这些串只对$f$有贡献。

problem2 link

给定一个字符串s,定义$f(i)$表示包含$s_{i}$的子列中回文串的个数。定义$y_{i}=(i+1)*x_{i}%1000000007$。计算所有$y_{i}$的抑或值。

定义$f(L,R)$表示仅由s[L~R]字符组成的回文串的个数,$g(L,R)$表示这样的回文串的个数:回文串的一半由s[0~L]中的字符构成,一半由s[R~|s|]字符组成。$f(L,R)=f(L+1,R)+f(L,R-1)-f(L+1,R-1)[s_{L}\neq s_{R}]$,$g(L,R)=g(L-1,R)+g(L,R+1)-g(L-1,R+1)[s_{L}\neq s_{R}]$。

$f$的理解方式:$f(L+1,R)=f(L+1,R-1)+{带有R不带有L}$,$f(L,R-1)=f(L+1,R-1)+{带有L不带有R}$,而如果$s_{L}\neq s_{R}$,那么$f(L+1,R-1)$就重算了;否则当$s_{L}和s_{R}$都要时的方案还是$f(L+1,R-1)$。这时候不需要减去。$g$的理解类似。

problem3 link

可以用$f[k][i], g[k][i]$表示初始化有$i$个,经过最多$k$轮后得到$b$个的最有策略的概率以及Limak的操作为最优策略的概率.这样需要一个$O(kn^2)$的复杂度.

这里符合最优策略的操作是连续的. 比如对于题目中的第四组数据$(a=10,b=20,k=2)$,有如下的关系:

初始时有$[0, 4]$,在2轮后能够到达20个的最优概率为0

初始时有$[5, 9]$,在2轮后能够到达20个的最优概率为0.25

初始时有$[10, 14]$,在2轮后能够到达20个的最优概率为0.5

初始时有$[15, 19]$,在2轮后能够到达20个的最优概率为0.75

初始时有$[20, oo]$,在2轮后能够到达20个的最优概率为1

这样在dp时,第二维的$n$就可以改为按照区间进行计算.

code for problem1

#include <string>
#include <vector> class BalancedStrings {
public:
std::vector<std::string> findAny(int N) {
std::vector<std::string> ans;
if (N <= 26) {
for (int i = 0; i < N; ++i) {
std::string s = "";
s += 'a' + i;
ans.push_back(s);
}
return ans;
}
for (int w = 0; w <= N; ++w) {
for (int x = w; w + x <= N; ++x) {
for (int y = x; w + x + y <= N; ++y) {
for (int z = y; w + x + y + z <= N; ++z) {
const int S = F(w) + F(x) + F(y) + F(z);
const int K = N - w - x - y - z;
if (K > 11) {
continue;
}
const int T = (S + 98) / 99;
if (T > K) {
continue;
}
for (int i = 1; i <= w; ++i) {
ans.push_back("w");
}
for (int i = 1; i <= x; ++i) {
ans.push_back("x");
}
for (int i = 1; i <= y; ++i) {
ans.push_back("y");
}
for (int i = 1; i <= z; ++i) {
ans.push_back("z");
}
for (int i = 0, x = 0; i < T; ++i) {
const char c = 'a' + i * 2;
std::string s = "";
s += c;
while (x < S && s.size() < 100) {
(s.size() & 1) ? s += c + 1 : s += c;
++x;
}
ans.push_back(s);
}
char cur = 'v';
while (ans.size() < N) {
std::string s = "";
s += cur;
ans.push_back(s);
--cur;
}
return ans;
}
}
}
}
return ans;
} private:
int F(int x) { return x * (x - 1) / 2; }
};

code for problem2

#include <string.h>
#include <algorithm>
#include <string>
#include <vector> class PalindromicSubseq {
static constexpr int kMod = 1000000007; public:
int solve(const std::string &s) {
int n = static_cast<int>(s.size());
int ans = 0;
std::vector<std::vector<int>> f(n, std::vector<int>(n, -1));
std::vector<std::vector<int>> g(n, std::vector<int>(n, -1));
for (int i = 0; i < n; ++i) {
int t = 0;
for (int j = 0; j < n; ++j) {
if (s[i] != s[j]) {
continue;
}
int ll = std::min(i, j);
int rr = std::max(i, j);
t += Mul(Dfs1(ll + 1, rr - 1, s, &f), Dfs2(ll - 1, rr + 1, s, &g));
t %= kMod;
}
if (t < 0) {
t += kMod;
}
ans ^= Mul(t, i + 1);
}
return ans;
} private:
int Mul(int a, int b) {
return static_cast<int>(static_cast<int64_t>(a) * b % kMod);
} int Dfs1(int ll, int rr, const std::string &s,
std::vector<std::vector<int>> *f) {
if (ll > rr) {
return 1;
}
if (ll == rr) {
return 2;
}
int &v = (*f)[ll][rr];
if (v != -1) {
return v;
}
v = (Dfs1(ll + 1, rr, s, f) + Dfs1(ll, rr - 1, s, f)) % kMod;
if (s[ll] != s[rr]) {
v = (v - Dfs1(ll + 1, rr - 1, s, f)) % kMod;
}
return v;
}
int Dfs2(int ll, int rr, const std::string &s,
std::vector<std::vector<int>> *f) {
if (ll < 0 || rr >= static_cast<int>(s.size())) {
return 1;
}
int &v = (*f)[ll][rr];
if (v != -1) {
return v;
}
v = (Dfs2(ll - 1, rr, s, f) + Dfs2(ll, rr + 1, s, f)) % kMod;
if (s[ll] != s[rr]) {
v = (v - Dfs2(ll - 1, rr + 1, s, f)) % kMod;
}
return v;
}
};

code for problem3

#include <string.h>
#include <algorithm>
#include <vector> class Fraction {
public:
Fraction(int64_t a = 0, int64_t b = 1) : a(a), b(b) {
int64_t t = Gcd(a, b);
a /= t;
b /= t;
if (a == 0) {
b = 1;
}
} Fraction operator+(const Fraction &other) const {
if (b == other.b) {
return Fraction(a + other.a, other.b);
}
int64_t t = Gcd(b, other.b);
int64_t q = b / t * other.b;
return Fraction(a * (q / b) + other.a * (q / other.b), q);
} double ToDouble() const { return 1.0 * a / b; } Fraction Div2() const {
if (a % 2 == 0) {
return Fraction(a / 2, b);
}
return Fraction(a, b * 2);
} bool operator<(const Fraction &other) const {
return a * other.b < b * other.a;
} bool operator<=(const Fraction &other) const {
return a * other.b <= b * other.a;
} bool operator==(const Fraction &other) const {
return a * other.b == b * other.a;
} private:
int64_t Gcd(int64_t a, int64_t b) const { return b == 0 ? a : Gcd(b, a % b); } int64_t a;
int64_t b;
}; class OptimalBetting {
public:
double findProbability(int a, int b, int k) {
std::vector<std::vector<double>> dp(2, std::vector<double>(b * 2 + 1, 1.0));
std::vector<std::pair<Fraction, int>> split;
split.emplace_back(0, 0);
split.emplace_back(1, b);
// Add sentry to simplfy implemention
split.emplace_back(0, b * 2 + 1);
for (int i = 1; i <= k; ++i) {
split = Solve(split, b, &(dp[(i & 1) ^ 1]), &(dp[i & 1]));
}
return dp[k & 1][a];
} private:
std::vector<std::pair<Fraction, int>> Solve(
const std::vector<std::pair<Fraction, int>> &last_split, int b,
std::vector<double> *last, std::vector<double> *curr) {
for (int i = 1; i <= b * 2; ++i) {
(*last)[i] += (*last)[i - 1];
}
auto Get = [&](int l, int r) -> double {
if (l > r) {
return 0;
}
return l == 0 ? (*last)[r] : (*last)[r] - (*last)[l - 1];
};
std::vector<std::pair<Fraction, int>> curr_split;
curr_split.emplace_back(0, 0);
(*curr)[0] = 1;
for (int i = 1; i < b; ++i) {
size_t left = 0, right = 1;
for (size_t j = 1; j < last_split.size(); ++j) {
if (last_split[j].second > i) {
left = j - 1;
right = j;
break;
}
}
Fraction maxp;
(*curr)[i] = 0;
while (right < last_split.size()) {
int upper = std::min(i - last_split[left].second,
last_split[right].second - i - 1);
int lower = left + 1 <= right - 1
? std::max(i - last_split[left + 1].second + 1,
last_split[right - 1].second - i)
: 0; Fraction rp =
(last_split[left].first + last_split[right - 1].first).Div2(); if (maxp <= rp) {
double p = Get(i - upper, i - lower) / (i + 1) / 2 +
Get(i + lower, i + upper) / (i + 1) / 2;
if (rp == maxp) {
(*curr)[i] += p;
} else {
(*curr)[i] = p;
}
maxp = rp;
}
if (last_split[left].second == i - upper) {
if (left == 0) {
break;
}
left--;
}
if (last_split[right].second == i + upper + 1) {
right++;
}
}
if (curr_split.back().first < maxp) {
curr_split.emplace_back(maxp, i);
}
}
for (int i = b; i <= b * 2; ++i) {
(*curr)[i] = 1;
}
curr_split.emplace_back(1, b);
curr_split.emplace_back(0, b * 2 + 1);
return curr_split;
}
};

topcoder srm 708 div1 -3的更多相关文章

  1. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

  2. Topcoder Srm 726 Div1 Hard

    Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...

  3. topcoder srm 714 div1

    problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...

  4. topcoder srm 738 div1 FindThePerfectTriangle(枚举)

    Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle wi ...

  5. Topcoder SRM 602 div1题解

    打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...

  6. Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

    Problem Statement      The Happy Letter game is played as follows: At the beginning, several players ...

  7. Topcoder SRM 584 DIV1 600

    思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...

  8. TopCoder SRM 605 DIV1

    604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...

  9. topcoder srm 575 div1

    problem1 link 如果$k$是先手必胜那么$f(k)=1$否则$f(k)=0$ 通过对前面小的数字的计算可以发现:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其 ...

随机推荐

  1. mysql----------局域网数据库:如何让navicat链接局域网其他的数据库。

    1.找到被链接的数据库,打开以后有一个自带的mysql数据库,打开以后下面有一个user表,把里面的第一条数据的第一个字段改成% 百分号,然后保存,重启数据库,搞定 2.如果是linux下的话,记得把 ...

  2. 软工网络15团队作业4——Alpha阶段敏捷冲刺4.0

    软工网络15团队作业4--Alpha阶段敏捷冲刺4.0 1.每天举行站立式会议,提供当天站立式会议照片一张. 2.项目每个成员的昨天进展.存在问题.今天安排. 成员 昨天已完成 今天计划完成 郭炜埕 ...

  3. kali linux wifi破解(aircrack)

    需要一个能监听的网卡 airmon-ng start wlan0(監聽網卡) airmon-ng check kill(清除其他有影响的環境) airodump-ng mon0 (掃描附近wifi) ...

  4. Hue中hive(hive cli)查询结果中显示列名,不带表名

    hive cli中显示列名 进入hive cli后 set hive.cli.print.header=true; 之后出现列名,但是带了表名前缀,由于网上没找到资料,于是到官网肉眼扫描所有参数,总算 ...

  5. javascript实现异步编程的4种方法

    1.回调函数. 2.事件监听 .  思路:采用事件驱动模式.任务的执行不取决于代码的顺序,而取决于某个事件是否发生 3.观察者模式 (发布/订阅模式)   代码如下: jQuery.subscribe ...

  6. Class__One HomeWork 实验报告

    石家庄铁道大学信息科学与技术学院       实验报告 2018年----2019年  第一学期               题目:   四则运算和验证码 课程名称:  JAVA语言程序设计 班    ...

  7. ElasticSearch相关文章推荐

    1. ElasticSearch查询:http://www.cnblogs.com/ljhdo/p/4486978.html 2. Elasticsearch Java API 的使用—多条件查询:h ...

  8. Linux基础命令---arp

    arp arp指令用来管理系统的arp缓冲区,可以显示.删除.添加静态mac地址.ARP以各种方式操纵内核的ARP缓存.主要选项是清除地址映射项并手动设置.为了调试目的,ARP程序还允许对ARP缓存进 ...

  9. AI赌神称霸德扑的秘密,刚刚被《科学》“曝光”了

    AI赌神称霸德扑的秘密,刚刚被<科学>“曝光”了 称霸德州扑克赛场的赌神Libratus,是今年最瞩目的AI明星之一. 刚刚,<科学>最新发布的预印版论文,详细解读了AI赌神背 ...

  10. Logstash 安装和使用

    下载地址 https://artifacts.elastic.co/downloads/logstash/logstash-5.6.8.zip 下载后解压,测试 #将键盘内容输出到控制台 logsta ...