problem1 link

肯定存在相邻两堆满足不会存在任何操作在这两堆之间进行。然后就成为一条链,那么只需要维护链的前缀和即可判断当前堆和前一堆之间需要多少次操作。

problem2 link

对于两个数字$x,y,x<y$,如果$y$不是$x$的倍数,那么一定有$lcm(x,y)+gcd(x,y)>x+y$。不妨假设$x=p_{1}^{a_{1}}p_{2}^{b_{1}},y=p_{1}^{a_{2}}p_{2}^{b_{2}}$,其中$p_{1},p_{2}$是两个不同的素数且$a_{1}<a_{2},b_{1}>b_{2}$,那么$lcm(x,y)+gcd(x,y)-x-y=p_{1}^{a_{2}}p_{2}^{b_{1}}+p_{1}^{a_{1}}p_{2}^{b_{2}}-p_{1}^{a_{1}}p_{2}^{b_{1}}-p_{1}^{a_{2}}p_{2}^{b_{2}}=p_{1}^{a_{1}}p_{2}^{b_{2}}(p_{1}^{a_{2}-a_{1}}-1)(p_{2}^{b_{1}-b_{2}}-1)>0$

所以任意两个进行一次操作之后,也就是$\frac{n(n-1)}{2}$次操作后,肯定会有一个最大的数字,它的各个质因子的指数是最大的,或者说对于素数$p$这个数字的$p$的指数不小于其他$n-1$个数字的$p$的指数;下一次对除了最大数字的其余$n-1$个数字再每两个进行这样的操作后,这 $n-1$个数字中的最大值的各个质因子的指数都是次大的。依次进行到最后即可。

比如$n=3$,这些数字为$2^{5}3^{8}5^{1},2^{7}3^{0}5^{10},2^{3}3^{4}5^{4}$,那么最后变成了$2^{7}3^{8}5^{10},2^{5}3^{4}5^{4},2^{3}3^{0}5^{1}$。

problem3 link

首先,将每个点看作是$(x,y)=(\frac{a+b}{2},\frac{a-b}{2})$,那么每次移动就是$a+1$或者$a-1$,以及$b+1$或者$b-1$。并且$a,b$是独立的。

所以$E(x^{n}y^{m})=E((\frac{a+b}{2})^{n}(\frac{a-b}{2})^m)=\sum_{i=0}^{n}\sum_{j=0}^{m}C_{n}^{i}C_{m}^{j}\frac{(-1)^{m-j}}{2^{n+m}}E(a^{i+j})E(b^{n+m-i-i})$

设$(x_{0},y_{0})=(\frac{A+B}{2},\frac{A-B}{2})$

那么最后的每个位置对应的$a,b$都可以分别看作是关于$A,B$的多项式,即$a=f(A),b=g(B)$.所有的这些位置逐个去计算这个多项式有点多,但是可以直接去求所有的位置对应的$a,b$对应的多项式的和。

比如当$t=0$时:

其中$(x_{0},y_{0})=(4,3),(A,B)=(11,-3)$

那么答案为$h(A,B)=(\frac{A+B}{2})^{n}(\frac{A-B}{2})^{m}=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}A^{i+j}B^{n+m-i-j}$

$=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}S_{0}(A,i+j)S_{0}(B,n+m-i-j)$

当$t=1$时(只画出了$(a,b)$):

那么答案为$h(A-1,B-1)+h(A-1,B+1)+h(A+1,B-1)+h(A+1,B+1)$

$=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}((A-1)^{i+j}+(A+1)^{i+j})((B-1)^{n+m-i-j}+(B+1)^{n+m-i-j})$

$=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}(2\sum_{2|(i+j-t)}C_{i+j}^{t}A^{t})(2\sum_{2|(n+m-i-j-t)}C_{n+m-i-j}^{t}B^{t})$

$=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}S_{1}(A,i+j)S_{1}(B,n+m-i-j)$

当$t=2$时:

答案为

$h((A-1)-1,(B-1)-1)+h((A-1)-1,(B-1)+1)+$

$h((A-1)+1,(B-1)-1)+h((A-1)+1,(B-1)+1)+$

$h((A-1)-1,(B+1)-1)+h((A-1)-1,(B+1)+1)+$

$h((A-1)+1,(B+1)-1)+h((A-1)+1,(B+1)+1)+$

$h((A+1)-1,(B-1)-1)+h((A+1)-1,(B-1)+1)+$

$h((A+1)+1,(B-1)-1)+h((A+1)+1,(B-1)+1)+$

$h((A+1)-1,(B+1)-1)+h((A+1)-1,(B+1)+1)+$

$h((A+1)+1,(B+1)-1)+h((A+1)+1,(B+1)+1)$

$=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}([(A-1)-1]^{i+j}+[(A-1)+1]^{i+j}+[(A+1)-1]^{i+j}+[(A+1)+1]^{i+j})S_{2}(B,n+m-i-j)$

$=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}S_{2}(A,i+j)S_{2}(B,n+m-i-j)$

其中$S_{2}(A,i+j)=2\sum_{2|(i+j-t_{2})}C_{i+j}^{t_{2}}\left (  (A-1)^{t_{2}}+(A+1)^{t_{2}}\right )$

$2\sum_{2|(i+j-t_{2})}C_{i+j}^{t_{2}}\left (  2\sum_{2|(t_{2}-t_{1})}C_{t_{2}}^{t_{1}}A^{t_{1}}\right )$

从上面的推导可以看出,$S_{i}(A,j)$的递推公式为:$S_{i}(A,j)=2\sum_{2|(j-p)}C_{j}^{p}S_{i-1}(A,p)$

初始条件为$S_{0}(A,j)=A^{j}$.从而可以用矩阵快速幂计算出所有的$S_{t}(A,k),S_{t}(B,k)$

那么最后的答案为$r=\sum_{i=0}^{n}\sum_{j=0}^{m}\frac{(-1)^{m-j}}{2^{n+m}}S_{t}(A,i+j)S_{t}(B,n+m-i-j)$

code for problem1

#include <algorithm>
#include <limits>
#include <vector> class MoveStones {
public:
long long get(const std::vector<int> &a, const std::vector<int> &b) {
long long sum = 0;
int n = static_cast<int>(a.size());
for (int i = 0; i < n; ++i) {
sum += a[i] - b[i];
}
if (sum != 0) {
return -1;
}
if (n == 1) {
return 0;
}
long long ans = std::numeric_limits<long long>::max();
for (int i = 0; i < n; ++i) {
long long pre = 0;
long long tmp = 0;
for (int j = 1; j <= n; ++j) {
long long t = a[(i + j) % n] - b[(i + j) % n];
tmp += std::abs(pre);
pre += t;
}
ans = std::min(ans, tmp);
}
return ans;
}
};

code for problem2

#include <algorithm>
#include <vector> constexpr int kMaxN = 10000000;
constexpr int kMaxPrimeNum = 670000;
constexpr int kMod = 1000000007; class GCDLCM2 {
public:
int getMaximalSum(const std::vector<int> &start, const std::vector<int> &d,
const std::vector<int> &cnt) {
CreatePrimeTable(); std::vector<std::vector<int>> f(kMaxPrimeNum);
auto Add = [&](int x) {
for (size_t i = 0; i < primes.size() && primes[i] * primes[i] <= x; ++i)
if (x % primes[i] == 0) {
int p = 1;
while (x % primes[i] == 0) {
p = p * primes[i];
x /= primes[i];
}
f[i].push_back(p);
}
if (x != 1) {
f[min_prime_indices[x]].push_back(x);
}
}; std::vector<int> a;
for (size_t i = 0; i < start.size(); ++i) {
for (int j = 0; j < cnt[i]; ++j) {
Add(start[i] + j * d[i]);
a.push_back(1);
}
}
int n = static_cast<int>(a.size());
for (size_t i = 0; i < primes.size(); ++i) {
if (!f[i].empty()) {
int s = static_cast<int>(f[i].size());
std::sort(f[i].begin(), f[i].end());
for (int j = 0; j < s; ++j)
a[n - s + j] =
static_cast<int>(1ll * a[n - s + j] * f[i][j] % kMod);
}
}
int sum = 0;
for (int i = 0; i < n; ++i) {
sum = (sum + a[i]) % kMod;
}
return sum;
} private:
std::vector<int> primes;
std::vector<size_t> min_prime_indices; void CreatePrimeTable() {
min_prime_indices.resize(kMaxN + 1);
primes.reserve(kMaxPrimeNum);
std::vector<bool> tag(kMaxN + 1);
for (int i = 2; i <= kMaxN; ++i) {
if (!tag[i]) {
min_prime_indices[i] = primes.size();
primes.push_back(i);
}
for (size_t j = 0; j < primes.size() && i * primes[j] <= kMaxN; ++j) {
tag[i * primes[j]] = true;
if (i % primes[j] == 0) {break;}
}
}
}
};

code for problem3

#include <vector>

class RandomWalkOnGrid {
static constexpr int kMod = 1000000007; public:
int getExpectation(int x0, int y0, int t, int n, int m) {
int total = n + m + 1;
std::vector<std::vector<long long>> c(total, std::vector<long long>(total));
c[0][0] = 1;
for (int i = 1; i < total; ++i) {
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; ++j) {
c[i][j] = Norm(c[i - 1][j - 1] + c[i - 1][j]);
}
}
std::vector<std::vector<long long>> transform(
total, std::vector<long long>(total, 0));
for (int i = 0; i < total; ++i) {
for (int j = 0; j <= i; ++j) {
if ((i - j) % 2 == 0) {
transform[j][i] = Norm(2 * c[i][j]);
}
}
}
transform = Pow(transform, t);
std::vector<std::vector<long long>> pa(1, std::vector<long long>(total));
std::vector<std::vector<long long>> pb(1, std::vector<long long>(total));
int a = Norm((x0 + y0) % kMod);
int b = Norm((x0 - y0) % kMod);
for (int i = 0; i < total; ++i) {
pa[0][i] = Pow(a, i);
pb[0][i] = Pow(b, i);
}
pa = Multiply(pa, transform);
pb = Multiply(pb, transform);
long long result = 0;
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= m; ++j) {
long long x = pa[0][i + j] * pb[0][n + m - i - j] % kMod;
if ((m - j) % 2 == 1) {
x = kMod - x;
}
Add(result, x * c[n][i] % kMod * c[m][j] % kMod);
}
}
result = result * Reverse(Pow(2, n + m)) % kMod;
return static_cast<int>(result);
} private:
std::vector<std::vector<long long>> Multiply(
const std::vector<std::vector<long long>> &a,
const std::vector<std::vector<long long>> &b) {
int n = static_cast<int>(a.size());
int m = static_cast<int>(b.size());
int p = static_cast<int>(b[0].size());
std::vector<std::vector<long long>> c(n, std::vector<long long>(p, 0));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < p; ++j) {
for (int k = 0; k < m; ++k) {
Add(c[i][j], a[i][k] * b[k][j] % kMod);
}
}
}
return std::move(c);
} std::vector<std::vector<long long>> Pow(std::vector<std::vector<long long>> a,
int t) {
int n = static_cast<int>(a.size());
std::vector<std::vector<long long>> result(n, std::vector<long long>(n, 0));
for (int i = 0; i < n; ++i) {
result[i][i] = 1;
}
while (t > 0) {
if (t % 2 == 1) {
result = Multiply(result, a);
}
a = Multiply(a, a);
t /= 2;
}
return std::move(result);
} long long Pow(long long a, long long b) {
long long result = 1;
while (b > 0) {
if (b % 2 == 1) {
result = result * a % kMod;
}
a = a * a % kMod;
b /= 2;
}
return result;
} void Add(long long &x, long long y) {
x += y;
if (x >= kMod) {
x -= kMod;
}
} long long Reverse(long long x) { return Pow(x, kMod - 2); } long long Norm(long long x) {
if (x >= kMod) {
x -= kMod;
} else if (x < 0) {
x += kMod;
}
return x;
}
};

 

参考链接:

https://blog.csdn.net/PhilipsWeng/article/details/52318811

topcoder srm 683 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 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 683 Div2 B

    贪心的题,从左向右推过去即可 #include <vector> #include <list> #include <map> #include <set&g ...

  7. Topcoder SRM 683 Div2 - C

    树形Dp的题,根据题意建树. DP[i][0] 表示以i为根节点的树的包含i的时候的所有状态点数的总和 Dp[i][1] 表示包含i结点的状态数目 对于一个子节点v Dp[i][0] = (Dp[v] ...

  8. Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

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

  9. Topcoder SRM 584 DIV1 600

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

随机推荐

  1. 关于Python veriable scope 的一点疑问

    在写程序中遇到了类似于以下代码的问题: #不会报错 a=1 def f(): print(a) f() #会报错 a=1 def f(): a+=1 f()

  2. linux降低内存后oracle数据库无法启动

    降低了虚拟机的内存之后发现虚拟机中的oracle数据库无法startup,原因是 target memory的数据有问题,然后在安装数据库的使用的是自动内存管理.涉及的一个系统文件 /dev/shm ...

  3. 关于django编码问题所导致的502错误

    在使用django开发的时候,访问网站出现了502错误,次数也比较平繁 uwsgi+nginx+django 在命令行下提示如下错误 : File "/opt/apps/python3/li ...

  4. MOG插件(葡萄牙语,略作翻译)

    这次记录下MOG大神的插件,自从我发现了这个插件,似乎开启了一个新世界诶~~~ 网址 https://atelierrgss.wordpress.com 1. MOG_YuruYuri.js CARA ...

  5. uvalive 11865 Stream My Contest

    题意: 有一个网络中心,和许多个城市,网络中心以及城市之间有若干条边,这些边有两个属性,最大带宽和修建费用. 现在要用最多不超过C的费用修建网络,使得每个城市都有网络连接,最大化最小带宽. 带宽限制是 ...

  6. session_start 统计实时访客人数

    void Session_Start(object sender, EventArgs e) { Application.Lock(); Application["OnLine"] ...

  7. php小数加减精度问题,比特币计算精度问题

    php小数加减精度问题,比特币计算精度问题 在php开发时,有小数加减的场景.结果发现不能够等于预想的值,bccomp比较二个高精确度数字.语法: int bccomp(string left ope ...

  8. Android Auto开发初探

    一.Android Auto 概述 二.Android Auto 使用方法 四.Android Auto应用开发 五.Android Auto开发总结 一.Android Auto 概述 最近物联网是 ...

  9. 算法训练 P0505

    一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积.阶乘的增长速度非常快,例如,13!就已经比较大了,已经无法存放在一个整型变量中:而35!就更大了,它已经无法存放在一个浮点型变量中.因此, ...

  10. python+selenium win32gui实现文件上传 enumerate()

    upload = dr.find_element_by_id('exampleInputFile0') upload.click() time.sleep(1) # win32gui dialog = ...