青岛赛训练
0-Fantasy of a Summation
时间:10月5号23点30
https://cn.vjudge.net/contest/258301#problem
这个题,题意给出是一个k重循环,每个循环i重1到n,循环体为 res = ( res + A[i1] + A[i2] + ... + A[iK] ) % MOD;最后res的值。
分析:组合数学+快速幂
解法:
对于每个A[i]都是一样的,
所以我们算出来总的A[i]出现的次数/n就可以知道每一个出现的次数
总的次数是(nk)*k,所以每个出现(n(k-1))k
所以答案是Sum(n^(k-1))*k%mod,最后用快速幂求解。
1-Pairs Forming LCM
时间:10月六号10:30
http://https://cn.vjudge.net/contest/258301#problem/B
分析:素数线性筛+唯一分解定律
解法:
给你一个数n 求满足lcm(a, b) == n, a <= b 的 (a,b) 的个数
容易知道 n 是a, b的所有素因子取在a, b中较大指数的积
先将n分解为素数指数积的形式
n=p1e1*p2e2...pk^ek;
a=p1a1*p2a2…pk^ak
b=p1b1*p2b2…pk^bk
对于a,b它们的最小公倍数为n,则a1<=e1,b1<=e1那么对于每个素因子pi的个数ei在a,b中的指数ai, bi 至少有一个等于ei, 另一个小于等于ei
先不考虑a, b的大小 对于每个素因子pi:
- 在a中的指数 ai == ei 那么 pi 在 b 中的指数可取 [0, ei] 中的所有数 有 ei + 1 种情况
- 在a中的指数 ai < ei 即 ai 在 [0, ei) 中 那么 pi 在 b 中的指数只能取 ei 有 ei 种情况
那么对与每个素因子都有 2ei + 1种情况 也就是满足条件的 (a, b) 有 π(2ei + 1)个 考虑大小时 除了 (n, n) 所有的情况都出现了两次 那么满足a<=b的有 (π(2*ei + 1)) / 2 + 1 个。
2-Incredible Chess
时间:10月六号22:30
http://https://cn.vjudge.net/contest/258301#problem/D
分析:博弈问题 nim游戏(这个游戏还没有系统的学习)
http://https://www.cnblogs.com/exponent/articles/2141477.html
解法:把每一列的棋子间隔(可以走的)看成Nim博弈中的石子数量,那么答案就所有差的异或...
3-Mergeable Stack
时间:10月七号9:00
http://https://vjudge.net/contest/258671#problem/D
分析:数据结构+模拟
解法:
题意 : 给你 1 2 3 个数,让你模拟栈的操作
1)将一个元素push到栈里;
2)将一个栈的栈顶元素输出;
3) 将两个栈合并;
模拟栈,如果用栈来操作,因为栈数目过多,爆内存
如果用vector也会爆
list容器就是一个双向链表,可以高效地进行插入删除元素,合并链表
输入输出用scanf printf
另外注意清空操作
for (int i = 1; i <= n; i++)//清空操作很必要
List[i].clear();//n个链表
模拟三个操作
if (op == 1) {
scanf("%d%d", &s, &v);
List[s].push_back(v);
}
else if (op == 2) {
scanf("%d", &s);
if (!List[s].empty()) {
printf("%d
", List[s].back());
List[s].pop_back();
}
else printf("EMPTY
");
}
else if (op == 3)
{
scanf("%d%d", &s, &t);
//c1.splice(c1.beg,c2) 将c2连接在c1的beg位置,释放c2
List[s].splice(List[s].end(), List[t]);
}
}
4-Travel along the Line
时间:10月七号16:00
http://https://vjudge.net/contest/258671#problem/E
分析:组合数学+逆元+组合数模板
解法:对于这个题,题目思路弄了大半天(那真是大半天),不是说题目意思,而是最后的逆元的步骤,最后发现分子乘以分母对MOD的逆元最后取模就AC了。。。
快速幂板子
ll quick_pow(ll a, ll b, int mod)//二进制写法
{
ll r = 1, base = a;
while (b)
{
if (b & 1)
r = (r*base) % mod;
base = (base*base) % mod;
b >>= 1;
}
return r;
}
组合数板子
ll C(ll n, ll m) {
if (m > n)
return 0;
if (n == m)return 1;
ll ans = 1;
for (int i = 1; i <= m; i++)
ans = ans * (n - i + 1) % MOD * quick_pow(i, MOD - 2,MOD) % MOD;
return ans;
}