problem1 link

每次枚举$S$的两种变化,并判断新的串是否是$T$的子串。不是的话停止搜索。

problem2 link

首先考慮增加1个面值为1的硬币后,$ways$数组有什么变化。设原来的方案为$w_{0}$,现在的为$w_{1}$。那么有$w_{1}[i]=w_{0}[i]+w_{0}[i-1]$。

$w_{0}: 1,5,6,7,0$

$w_{1}: 1,6,11,13,7$

如果将上面的例子中的$w_{0},w_{1}$看作多项式的话,就有$w_{0}=1+5x+6x^{2}+7x^{3}$,$w_{1}=1+6x+11x^{2}+13x^{3}+7x_{4}=(1+5x+6x^{2}+7x^{3})(1+x)=(1+x)w_{0}$

同理,面值为1的硬币增加$k$的话,就有$w_{1}[i]=\sum_{t=0}^{k}w_{0}[i-t]$,即多项式的话就是$w_{1}=(1+x)^{k}w_{0}$。如果是面值$v$的增加$k$的话,就是$w_{1}=(1+x^{v})^{k}w_{0}$。所以这里跟面值是1的是类似的。只分析面试为1的即可。

题目中是已知$w_{1}$来计算$w_{0}$,那么有$w_{0}=\frac{w_{1}}{(1+x)^{k}}$。

因为$ \frac{1}{1+x}=1-x+x^{2}-x^{3}+x^{4}...\rightarrow  \frac{1}{(1+x)^{k}}=(1-x+x^{2}-x^{3}+x^{4}...)^{k}=\sum_{n\geq 0}(-1)^{n}C_{k+n-1}^{n}x^{n}$

所以如果$w_{1}=\sum_{i=0}^{D}a_{i}x^{i},w_{0}=\sum_{i=0}^{D}b_{i}x^{i}$

那么$b_{D}=\sum_{i\geq 0}(-1)^{i}C_{k+i-1}^{i}a_{D-i}$

如果是面值为$v$的增加$k$个的话就有$b_{D}=\sum_{i\geq 0}(-1)^{i}C_{k+i-1}^{i}a_{D-iv}$.

这个代码是$O(qD)$的复杂度。不过一直超时,不知道怎么回事。

problem3 link

将卡片以及操作看作是图的顶点和边。每个节点有一个颜色$A$或者$B$。首先,节点0的颜色永远不会变。最后所有节点的颜色都会变成节点0的颜色。假设$[1,n-1]$中与节点0相同颜色的节点有$x$个。将这些节点称为$good$

一个结论是在任意次操作后(直到结束前),所有$x$个$good$节点的分布情况是等概率的。

所以可以计算一开始有$0,1,2,...,n-1$个$good$节点的期望。设$i$个点的时候的期望为$f(i)$。那么经过一次操作后,$i$个$good$点有可能变为$i-1,i,i+1$个$good$点,设概率为$p_{1},p_{2},p_{3}$

其中$p_{1}=\frac{C_{i+1}^{2}+C_{n-(i+1)}^{2}}{C_{n}^{2}}$,$p_{2}=\frac{i(n-(i+1))}{2C_{n}^{2}},p_{3}=1-p_{1}-p_{2}$

转移方程为$f(i)=p_{1}f(i)+p_{2}f(i-1)+p_{3}f(i+1)+t$,

$t=\left\{\begin{matrix} 0 & i \neq s\\  \frac{1}{C_{n-1}^{s}} & i=s \end{matrix}\right.$

$s$为输入中$good$ 节点的个数。

求出$f$数组后,答案为$\frac{\sum_{i=0}^{n-1}f(i)C_{n-1}^{i}}{2^{n}}$

code for problem1

#include <algorithm>
#include <string>
#include <unordered_set>
#include <vector> class ABBADiv1 {
public:
std::string canObtain(const std::string &a, const std::string &b) {
int n = static_cast<int>(b.size());
sub_sets.resize(n + 1);
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) {
int len = j - i + 1;
std::string s = b.substr(i, len);
sub_sets[len].insert(s);
std::reverse(s.begin(), s.end());
sub_sets[len].insert(s);
}
}
if (Dfs(a, b)) {
return "Possible";
}
return "Impossible";
} private:
std::vector<std::unordered_set<std::string>> sub_sets; bool Exist(const std::string &s) { return sub_sets[s.size()].count(s) > 0; } bool Dfs(const std::string &a, const std::string &target) {
if (a.size() == target.size()) {
return a == target;
}
if (Exist(a + 'A') && Dfs(a + 'A', target)) {
return true;
}
std::string new_a = a + 'B';
std::reverse(new_a.begin(), new_a.end());
return Exist(new_a) && Dfs(new_a, target);
}
};

code for problem2

#include <algorithm>
#include <vector> constexpr int kMAXN = 1002000;
long long p[kMAXN];
long long q[kMAXN]; class ChangingChange {
public:
std::vector<int> countWays(std::vector<int> ways,
std::vector<int> valueRemoved,
std::vector<int> numRemoved) {
constexpr int kMod = 1000000007;
int n = ways.size() - 1;
int m = valueRemoved.size();
auto ModInv = [&](long long k) {
int t = kMod - 2;
long long r = 1;
while (t > 0) {
if (t % 2 == 1) {
r = r * k % kMod;
}
t /= 2;
k = k * k % kMod;
}
return r;
};
p[0] = 1;
for (int i = 1; i < kMAXN; ++i) {
p[i] = i * p[i - 1] % kMod;
}
q[kMAXN - 1] = ModInv(p[kMAXN - 1]);
for (int i = kMAXN - 2; i >= 0; --i) {
q[i] = q[i + 1] * (i + 1) % kMod;
}
std::vector<int> result(m);
for (int id = 0; id < m; ++id) {
int k = valueRemoved[id];
int num = numRemoved[id];
long long total = 0;
for (int i = 0, t = n / k; i <= t; ++i) {
long long a = p[num + i - 1] * q[i] % kMod * q[num - 1] % kMod *
ways[n - i * k] % kMod;
if ((i & 1) == 0) {
total += a;
} else {
total += kMod - a;
}
if (total >= kMod) {
total -= kMod;
}
}
result[id] = static_cast<int>(total);
}
return result;
}
};

code for problem3

#include <string>

constexpr int kMod = 1000000007;
constexpr int kMaxN = 1001; int a[kMaxN][kMaxN];
int c[kMaxN][kMaxN];
int f[kMaxN]; class WarAndPeas {
public:
int expectedPeas(const std::string &state) {
int n = static_cast<int>(state.size());
c[0][0] = 1;
for (int i = 1; i <= n; ++i) {
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; ++j) {
c[i][j] = Add(c[i - 1][j - 1], c[i - 1][j]);
}
}
int s = 0;
for (int i = 1; i < n; ++i) {
if (state[i] == state[0]) {
++s;
}
}
for (int i = 0; i < n; ++i) {
int p1 = Mul(Add(c[i + 1][2], c[n - i - 1][2]), Inverse(c[n][2]));
int p2 = Mul(Mul(i, n - i - 1), Inverse(2 * c[n][2]));
int p3 = Add(1, kMod - Add(p1, p2));
if (i == n - 1) {
p1 = 0;
}
p1 = Add(p1, kMod - 1);
if (i == s) {
a[i][n] = Mul(kMod - 1, Inverse(c[n - 1][s]));
}
a[i][i] = p1;
if (i > 0) {
a[i][i - 1] = p2;
}
if (i < n - 1) {
a[i][i + 1] = p3;
}
}
Solve(n);
int result = 0;
for (int i = 0; i < n; ++i) {
result = Add(result, Mul(f[i], c[n - 1][i]));
}
result = Mul(result, Inverse(Pow(2, n)));
return result;
} private:
void Solve(int n) {
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) {
if (a[j][i] != 0) {
for (int k = 0; k <= n; ++k) {
std::swap(a[i][k], a[j][k]);
}
break;
}
}
for (int j = 0; j < n; ++j) {
if (j == i || a[j][i] == 0) {
continue;
}
int t = Mul(a[j][i], Inverse(a[i][i]));
for (int k = 0; k <= n; ++k) {
a[j][k] = Add(a[j][k], kMod - Mul(a[i][k], t));
}
}
}
for (int i = 0; i < n; ++i) {
f[i] = Mul(a[i][n], Inverse(a[i][i]));
}
} int Pow(long long a, int b) {
long long r = 1;
while (b > 0) {
if (b % 2 == 1) {
r = r * a % kMod;
}
a = a * a % kMod;
b /= 2;
}
return static_cast<int>(r);
} int Inverse(int x) { return Pow(x, kMod - 2); } int Add(int x, int y) {
x += y;
if (x >= kMod) {
x -= kMod;
}
return x;
} int Mul(long long x, long long y) { return static_cast<int>(x * y % kMod); }
};

topcoder srm 663 div1的更多相关文章

  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 480 div1

    problem1 link 直接模拟即可. problem2 link 首先,网关一定是安装在client与server之间的链路上.而不会安装在client与client之间的链路上.对于一条路径c ...

  4. topcoder srm 714 div1

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

  5. topcoder srm 738 div1 FindThePerfectTriangle(枚举)

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

  6. Topcoder SRM 602 div1题解

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

  7. Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

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

  8. Topcoder SRM 584 DIV1 600

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

  9. TopCoder SRM 605 DIV1

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

随机推荐

  1. hive-drop-import-delims选项对oracle的clob无效

    工作过程中发现了用sqoop将oracle中的数据导入到hive时,会因为oracle中类型为clob的字段中存在换行时,会造成hive的数据错位.即使加上了 --hive-drop-import-d ...

  2. Oracle TNS-01190: The user is not authorized to execute the requested listener command

    今天,在玩 lsnrctl命令,是为了了解Oracle的一些配置. 当执行 show inbound_connect_timeout 命令之后,提示了错误信息: TNS-01190: The user ...

  3. Unity shader学习之Alpha Blend

    通过 ShaderLab 的 AlphaBlend 能够实现真正的半透明效果. 使用 AlphaBlend 时,需要关闭深度写入 ZWrite Off,但得非常小心物体的渲染顺序, RenderQue ...

  4. Git-什么是分支

    为了理解什么是分支,我们先要回顾Git是如何存储数据的. Git并不会保存文件的差异值或者说变化量,而是直接保存文件的快照. 在Git中提交时,会保存一个commit对象,该对象包含一个指向暂存内容快 ...

  5. Oil Deposits HDU 1241

    The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu ...

  6. codefroces 266

    D题说的是 你选定一个区间如[l r] 将这个区间内的每个数都加上1,然后求将这整个整个序列都变成h的方案数有多少种 没有一个位置会有超过1次方[  或者放 ] 考虑当前位置放的是什么 有5种 - 不 ...

  7. Linux基础命令---显示登录用户w

    w 显示哪些用户登录,并且显示用户在干什么.报头按此顺序显示当前时间.系统运行时间.当前登录用户数以及过去1.5和15分钟的系统平均负载.接着为每个用户显示以下条目:登录名.TTY名称.远程主机.登录 ...

  8. いろはちゃんとマス目 / Iroha and a Grid (组合数学)

    题目链接:http://abc042.contest.atcoder.jp/tasks/arc058_b Time limit : 2sec / Memory limit : 256MB Score ...

  9. zabbix 服务端安装(server)

    zabbix版本:Zabbix 2.2 LTS 备注:Linux下安装zabbix需要有LAMP或者LNMP运行环境 准备篇: 一.Web环境:Nginx+MySQL+PHP CentOS 7.0编译 ...

  10. 每日linux命令学习-rpm命令

    rpm命令 rpm是一款强大的Redhat软件包管理工具,可创建.安装.查询.验证.升级和卸载每个软件包,软件包是存储文件,包括需要安装的文件和名称.版本.说明等报信息. rpm默认支持7种操作模式, ...