Avian Darts
Boring Task
Cookies
#include
using namespace std;
typedef long long ll;
const ll mod = 998244353;
ll qpow(ll a, ll b) {
a %= mod;
ll res = 1;
while (b) {
if (b & 1)res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll n;
ll Cn3 = (24 * 25 * 26) % mod;// C(n,3)
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
if (n <= 3)
cout << qpow(26, n) << endl;
else
cout << Cn3 << endl;
}
return 0;
}
赛中交的代码赛后疯狂T,感谢测评姬放过……
已知斐波那契有如下:
F ( n ) = 1 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] F(n)=\frac{1}{\sqrt 5}\bigg[ \bigg( \frac{1+\sqrt 5}{2} \bigg)^n- \bigg( \frac{1-\sqrt 5}{2} \bigg)^n \bigg] F(n)=51[(21+5)n−(21−5)n]
再扩展一下每一项的k次幂
F ( n ) k = ( 1 5 ) k [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] k F(n)^k=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[ \bigg( \frac{1+\sqrt 5}{2} \bigg)^n- \bigg( \frac{1-\sqrt 5}{2} \bigg)^n \bigg]^k F(n)k=(51)k[(21+5)n−(21−5)n]k
其中,令 a = ( 1 + 5 2 ) n a=\bigg( \frac{1+\sqrt 5}{2} \bigg)^n a=(21+5)n
b = ( 1 − 5 2 ) n b=\bigg( \frac{1-\sqrt 5}{2} \bigg)^n b=(21−5)n
则有
[ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] k = ( a n − b n ) k \bigg[ \bigg( \frac{1+\sqrt 5}{2} \bigg)^n- \bigg( \frac{1-\sqrt 5}{2} \bigg)^n \bigg]^k=(a^n-b^n)^k [(21+5)n−(21−5)n]k=(an−bn)k
注意到,这是一个二项式
( a n − b n ) k = C k 0 ( a n ) 0 ( − b n ) k + C k 1 ( a n ) 1 ( − b n ) k − 1 + . . . . . + C k k ( a n ) k ( − b n ) 0 = ∑ i = 0 k ( − 1 ) k − i ( a n ) i ( b n ) k − i (a^n-b^n)^k=C^0_k(a^n)^0(-b^n)^k+C^1_k(a^n)^1(-b^n)^{k-1}+.....+C^k_k(a^n)^k(-b^n)^0\\=\sum^k_{i=0}(-1)^{k-i}(a^n)^i(b^n)^{k-i} (an−bn)k=Ck0(an)0(−bn)k+Ck1(an)1(−bn)k−1+.....+Ckk(an)k(−bn)0=i=0∑k(−1)k−i(an)i(bn)k−i
注意一下,这里把 − b n -b^n −bn 里的负号提取出来了,用处在后面会提到
因此,
F ( n ) k = ( 1 5 ) k [ ∑ i = 0 k ( − 1 ) k − i C k i ( a n ) i ( b n ) k − i ] F(n)^k=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[\sum^k_{i=0}(-1)^{k-i}C^i_k(a^n)^i(b^n)^{k-i}\bigg] F(n)k=(51)k[i=0∑k(−1)k−iCki(an)i(bn)k−i]
结合题目给出的n、c、k,用c替换上式的n
F ( c ) k = ( 1 5 ) k [ ∑ i = 0 k ( − 1 ) k − i C k i ( a c ) i ( b c ) k − i ] F(c)^k=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[\sum^k_{i=0}(-1)^{k-i}C^i_k(a^c)^i(b^c)^{k-i}\bigg] F(c)k=(51)k[i=0∑k(−1)k−iCki(ac)i(bc)k−i]
然后再看看F(2c)时的式子
F ( 2 c ) k = ( 1 5 ) k [ ( 1 + 5 2 ) 2 c − ( 1 − 5 2 ) 2 c ] k = ( 1 5 ) k [ ∑ i = 0 k ( − 1 ) k − i C k i ( a 2 c ) i ( b 2 c ) k − i ] = ( 1 5 ) k [ ∑ i = 0 k ( − 1 ) k − i C k i ( ( a c ) i ( b c ) k − i ) 2 ] F(2c)^k=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[ \bigg( \frac{1+\sqrt 5}{2} \bigg)^{2c}- \bigg( \frac{1-\sqrt 5}{2} \bigg)^{2c} \bigg]^k\\=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[\sum^k_{i=0}(-1)^{k-i}C^i_k(a^{2c})^i(b^{2c})^{k-i}\bigg]\\=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[\sum^k_{i=0}(-1)^{k-i}C^i_k\bigg((a^{c})^i(b^{c})^{k-i}\bigg)^2\bigg] F(2c)k=(51)k[(21+5)2c−(21−5)2c]k=(51)k[i=0∑k(−1)k−iCki(a2c)i(b2c)k−i]=(51)k[i=0∑k(−1)k−iCki((ac)i(bc)k−i)2]
可以发现 F ( c ) F(c) F(c) 与 F ( 2 c ) F(2c) F(2c) 之间,二项式里每一项的 ( a c ) i ( b c ) k − i (a^{c})^i(b^{c})^{k-i} (ac)i(bc)k−i 翻倍了
由此推出 F ( n c ) F(nc) F(nc) 时的式子
F ( n c ) k = ( 1 5 ) k [ ∑ i = 0 k ( − 1 ) k − i C k i ( ( a c ) i ( b c ) k − i ) n ] F(nc)^k=\bigg( \frac{1}{\sqrt 5} \bigg)^k\bigg[\sum^k_{i=0}(-1)^{k-i}C^i_k\bigg((a^{c})^i(b^{c})^{k-i}\bigg)^n\bigg] F(nc)k=(51)k[i=0∑k(−1)k−iCki((ac)i(bc)k−i)n]
对于各个 F ( x c ) x = 1... n F(xc)_{x=1...n} F(xc)x=1...n的二项式里第 i i i 项,存在公比 q = ( a c ) i ( b c ) k − i q=(a^{c})^i(b^{c})^{k-i} q=(ac)i(bc)k−i,可以等比公式求和统计
S ( n ) = a 1 × q n − 1 q − 1 S(n)=a_1\times\frac{q^n-1}{q-1} S(n)=a1×q−1qn−1
前面提取的负号,也是为了方便后面的求和统计
重点:
模数 p = 1 0 9 + 9 p=10^9+9 p=109+9 是一个质数
1 5 \cfrac{1}{\sqrt 5} 51 在模意义下需要借助 二次剩余 来求,即 x 2 = 5 m o d 1 0 9 + 9 x^2=5\mod {10^9+9} x2=5mod109+9
得到x的一个解: x = 5 = 383008016 x=\sqrt 5=383008016 x=5=383008016
再结合费马小定理求出斐波那契公式里的 a a a 和 b b b
a = 1 + 5 2 = 691504013 b = 1 − 5 2 = 308495997 1 5 = 276601605 a= \frac{1+\sqrt 5}{2} =691504013\\b= \frac{1-\sqrt 5}{2} =308495997\\\frac{1}{\sqrt 5}=276601605 a=21+5=691504013b=21−5=30849599751=276601605
其次 n , c ≤ 1 0 18 n,c\le10^{18} n,c≤1018 数据过大,需要 欧拉降幂
公式如下:
a b m o d p = a b m o d φ ( p ) + φ ( p ) m o d p a^b \mod p=a^{b \mod \varphi(p)+\varphi(p)}\mod p abmodp=abmodφ(p)+φ(p)modp
并且由于 1 0 9 + 9 10^9+9 109+9是个质数,可以根据欧拉函数的性质直接得出phi值就是 模数本身-1
φ ( 1 0 9 + 9 ) = 1 0 9 + 8 \varphi(10^9+9)=10^9+8 φ(109+9)=109+8
ps:如果还T的话,scanf改cin、关掉一两个数组,你就可以过去了……
// 赛后ac代码
#include
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 9;
const int N = 1e5 + 10;
ll qpow(ll a, ll b) {
a %= mod;
ll res = 1;
while (b) {
if (b & 1)res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll Phi = mod - 1;//欧拉降幂
ll euler(ll a, ll b) {
return qpow(a, ((b % Phi) + Phi));
}
ll fac[N], inv[N];
void init(int n) {
fac[0] = inv[0] = 1;
for (int i = 1; i <= n; ++i) {
fac[i] = fac[i - 1] * i % mod;
inv[i] = inv[i - 1] * qpow(i, mod - 2) % mod;
}
}
ll C(int n, int m) {
if (n < m || m < 0)return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
ll Add(ll x, ll y) {
if (x < 0)x += mod;
if (y < 0) y += mod;
return (x + y) % mod;
}
ll Mul(ll x, ll y) {
x %= mod;
y %= mod;
return x * y % mod;
}
ll n, c;
int k;
ll a = 691504013;// (1+sqrt(5))/2
ll b = 308495997;// (1-sqrt(5))/2
ll Inv5 = 276601605;// 1/sqrt(5)
ll A, B, A_B, q;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
init(100000);
int T;
cin >> T;
while (T--) {
cin >> n >> c >> k;
A = qpow(a, c);// a^c
B = qpow(b, c);// b^c
A_B = Mul(A, qpow(B, mod - 2));// A/B
q = qpow(B, k);//公比
ll res = 0, tmp;
for (int i = 0; i <= k; i++) {
//if (q == 0)continue; mod为质数 永远不会有公比为0的时候
if (q == 1) {
tmp = n % mod;
} else {
tmp = Mul(Mul(Add(euler(q, n), mod - 1), qpow(Add(q, mod - 1), mod - 2)), q);
}
tmp = Mul((C(k, i) * ((k - i) & 1 ? -1 : 1)), tmp);
res = Add(res, tmp);
q = Mul(q, A_B);
}
res = Mul(res, qpow(Inv5, k));
cout << res << endl;
}
return 0;
}
#include
using namespace std;
const int N = 1e5 + 3;
vector<int> e[N], E[N];
int vis[N];
int a[N];
int u[N], v[N], d[N];
int n, m;
struct segTree {
#define ls (o<<1)
#define rs (o<<1|1)
struct node {
int l, r;
int sum;
} t[N << 2];
int cnt[N];
void pushup(int o) {
t[o].sum = t[ls].sum + t[rs].sum;
}
//不带数组 建树
void build(int o, int l, int r) {
t[o].l = l;
t[o].r = r;
t[o].sum = 0;
if (l == r) {
cnt[l] = 0;
return;
}
int mid = l + r >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
}
int query(int o) {
if (t[o].l == t[o].r) {
return t[o].l;
}
int len = t[o].r - t[o].l + 1;
if (t[ls].sum >= (len - (len >> 1)))
return query(rs);
else return query(ls);
}
void add(int o, int pos, int val) {
if (t[o].l == t[o].r) {
cnt[t[o].l] += val;
if (cnt[t[o].l] > 0)
t[o].sum = 1;
else
t[o].sum = 0;
return;
}
int mid = t[o].l + t[o].r >> 1;
if (pos <= mid) add(ls, pos, val);
else add(rs, pos, val);
pushup(o);
}
} ST[351];
int id[N], dfn = 0;
int Hash[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> n >> m;
//init
dfn = 0;
for (int i = 1; i <= n; i++) {
e[i].clear();//所有边
E[i].clear();//大点连边
vis[i] = d[i] = 0;
id[i] = 0;
}
for (int i = 1; i <= n; i++) {
cin >> a[i];
a[i]++;//在原来的基础上+1 便于线段树维护
}
for (int i = 1; i <= m; i++) {
cin >> u[i] >> v[i];
e[u[i]].push_back(v[i]);
e[v[i]].push_back(u[i]);
d[u[i]]++;
d[v[i]]++;
}
int block = 1000;
for (int i = 1; i <= n; i++) {
// 区分 部分度数超过block的点为大点 没有超过的为小点
if (d[i] > block) {
vis[i] = 1; // 标记大点
}
}
for (int i = 1; i <= m; i++) {
if (vis[v[i]]) // 当v[i]是大点时 需要对v[i]建线段树 如果u[i]要修改权值 则v[i]对应的线段树也要修改
E[u[i]].push_back(v[i]);
if (vis[u[i]])
E[v[i]].push_back(u[i]);
}
for (int i = 1; i <= n; i++) {
if (vis[i]) {
id[i] = ++dfn; // 记录点i对应的是哪颗线段树
ST[dfn].build(1, 1, d[i] + 1);
for (int j : e[i]) {
if (a[j] <= d[i])
ST[dfn].add(1, a[j], 1);
}
}
}
int q, op, x, y;
cin >> q;
while (q--) {
cin >> op;
if (op == 1) {
//将 a[x]修改成y
cin >> x >> y;
y++;
for (int z:E[x]) {
if (vis[z]) { // 如果相连的是大点
if (a[x] <= d[z])
ST[id[z]].add(1, a[x], -1);
if (y <= d[z]) // 如果y值比点z的度数还大 显然y不可能是F(z)的答案
ST[id[z]].add(1, y, 1);
}
}
a[x] = y;
} else { //op=2
cin >> x;
if (vis[x]) {
cout << ST[id[x]].query(1) - 1 << endl;
} else {
// 用set会t
for (int i = 1; i <= d[x]; i++)
Hash[i] = 0;
for (int z:e[x]) {
if (a[z] > d[x])continue;
Hash[a[z]] = 1;
}
int res = 1;
for (int i = 1; i <= d[x]; i++)
if (!Hash[i]) {
res = i;
break;
}
cout << res - 1 << endl;
}
}
}
}
return 0;
}
Hunting Monsters
Integral Calculus
#include
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const int N = 1e6 + 10;
int n;
int sgn(double x) {
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
else return 1;
}
//判断小数和0是否等于
struct Line {
// y=kx+b
ll k, b;
bool operator==(const Line line) const {
return k == line.k && b == line.b;
}
bool operator<(const Line line) const {
if (b == line.b) {
return k < line.k;
}
return b > line.b;
}
} L[N];
int Stack[N], top = 0;
int check(Line l1, Line l2, Line l3) {
double x1 = (double) (l2.b - l1.b) / (double) (l1.k - l2.k); // 第一和第二的交点
double x2 = (double) (l3.b - l2.b) / (double) (l2.k - l3.k); // 新的直线和第二的交点
if (sgn(x1 - x2) > 0) {
return 1;
} else if (sgn(x1 - x2) == 0) {
return 2;
}
return 3;
// 1 (x1,y1)在 (x2,y2)的左边
// 2 (x1,y1)和(x2,y2)是同一个点
// 3 (x1,y1)在 (x2,y2)的右边
}
int vis[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
ll p, a;
cin >> T;
while (T--) {
// init
top = 0;
cin >> n;
// y=1/2at^2+p -> 2y=a(t^2)+2p
for (int i = 1; i <= n; i++) {
cin >> p >> a;
L[i].k = a;
L[i].b = p * 2;
// init
vis[i] = 0; // 用于判断是否重线
}
sort(L + 1, L + 1 + n);
for (int i = 1, first, second, x; i <= n; i++) {
if (top && L[first = Stack[top]].k >= L[i].k) { // L[i]永远追不上第一
if (L[first] == L[i]) vis[first] = 1;//同一条直线 第一也不能要
continue;
}
if (top < 2) {
// 但是也存在后面的点和第一是同一个起点 加速度比第一大 即一开始大家都是第一 后一秒L[i]超过第一
if (top == 1 && L[first].b == L[i].b) {
Stack[top] = i;
} else
Stack[++top] = i;
} else {//top>=2
// 如果第一与第二的交点 在 第二与L[i]的右边 说明L[i]比第一先成领跑
while (top > 1 && check(L[first], L[second = Stack[top - 1]], L[i]) != 3) {
first = second;
top--;//踢掉第一
}
Stack[++top] = i;
}
}
int res = 0;
for (int i = 1; i <= top; i++) {
if (!vis[Stack[i]]) {
res++;
}
}
cout << res << endl;
}
return 0;
}
Math is Simple
Minimum Index
Mow