SHOI的题目质量好高啊,感觉都是些不错的题目……(
我都不会做)
LOJ 2142「SHOI2017」相逢是问候
题意:给定一个序列,在模
p
意义下,兹瓷区间对给出的一个常数
分析:一看到模意义,我们马上想到指数循环节,由于
我们会发现,这个定理大致意思就是说,找另一个 n ,使得
那么进一步的,再套几层下去,就会相当于模 φ(φ(p)),φ(φ(φ(p))),⋯
很明显 O(logn) 次之后就有 m< 模数,就是不用修改了
然后和区间取模就很类似了,利用线段树维护暴力修改和区间求和,每次暴力修改,如果发现不用修改了(对原来指数的模已经相当于模 1 了),那就不改了,否则暴力递归下去修改
直接做是
LOJ 2143「SHOI2017」组合数问题
题意:从
nk
个物品里选模
k
余
分析:容易看出,如果我们设一个
但是还有更快的做法,就是考虑到
f(2n,t)∑i+j=tf(n,i)×f(n,j)
就是枚举前一段和后一段选的个数,时间复杂度
O(k2logn)
# include <cstdio>
# include <cstring>
# define mem(x,v) memset(x,v,sizeof(x))
# define N 1000000000
# define K 50
typedef long long LL;
LL p;
int k;
struct MVec {
LL a[K * 2];
MVec(bool u = false) : a() {
if (u) a[0] = 1;
}
LL &operator[](int i) { return a[i]; }
const LL &operator[](int i) const { return a[i]; }
};
inline MVec &operator%=(MVec &a, int k) {
for (int i = k; i < k * 2; i++) {
(a[i - k] += a[i]) %= p;
a[i] = 0;
}
return a;
}
inline MVec operator*(const MVec &a, const MVec &b) {
MVec res;
for (int i = 0; i < k; i++) {
for (int j = 0; j < k; j++) {
(res[i + j] += a[i] * b[j] % p) %= p;
}
}
res %= k;
return res;
}
inline MVec pow(MVec a, LL n) {
MVec res(true);
for (; n; n >>= 1, a = a * a) if (n & 1) res = res * a;
return res;
}
int main() {
int n, r;
scanf("%d%lld%d%d", &n, &p, &k, &r);
MVec a;
a[1] = 1;
a[0] = 1;
a %= k;
MVec res = pow(a, (LL)n * k);
printf("%lld\n", res[r]);
}
LOJ 2190「SHOI2014」信号增幅仪
题意:平面上给一些点,问最小椭圆覆盖,其中椭圆长轴和短轴的比是给出的一个
λ
,同时长轴要求固定在与
x
轴夹
分析:这里转化的思路还是很兹瓷的……毕竟我们还是会最小圆覆盖的
考虑将整个图转到长轴的方向上,然后将整个图短轴方向上扩大
λ
(防止精度损失),然后就还是一个最小圆覆盖辣……
最小圆覆盖用随机增量法很好写……所以是期望
O(n)
的
LOJ 2039「SHOI2015」激光发生器
题意:给一条射线,每次碰到一条线段
i
,,就会发生反射,反射角
分析:这是一道暴力题……直接暴力判断肯定不会超,而且数据范围其实可以往上放得多很多的qaq