index > 牛客多校第五场
题号 | 标题 | 通过率 | 做法 | 状态 |
---|---|---|---|---|
A | digits 2 | 1017/2383 | 签到 | √+ |
B | generator 1 | 555/3660 | 矩阵快速幂/十进制优化 | ○ |
C | generator 2 | 37/626 | ||
D | generator 3 | 4/23 | ||
E | independent set 1 | 45/110 | ||
F | maximum clique 1 | 93/838 | ||
G | subsequence 1 | 522/2513 | dp | √- |
H | subsequence 2 | 286/1366 | ||
I | three points 1 | 139/2701 | ||
J | three points 2 | 7/76 |
○
代表赛后补题√+
代表赛内我通过的√-
代表赛内不是我做的√-○
代表赛内不是我做的,补了好像我们脑子也不是转得很快,所以还是废了点功夫才想到拼接。
比赛时莫名其妙地以为,矩阵乘法也可以欧拉降幂。然后从头wa到结束。
其实用了一个很巧妙的想法。
题意就是给一个公式(显然是用二维矩阵快速幂求的)。然后给你一个无比庞大的n( 1 0 1000000 10^{1000000} 101000000)。但是个数存不下来,转二进制又非常麻烦。
那么咋办?可以直接用十进制来做呀,我们回顾一下二进制快速幂就是取二进制每一位是1的时候,把乘幂处理好的底数乘上去。由于二进制每位只有两个选择,所以比较简单。
十进制也完全可以处理底数 b a s e = b a s e 10 base = base^{10} base=base10,但是二进制每一位还有9个选择,那也好办,如果这一位是 x x x, r e s = r e s × ( b a s e 10 ) x res =res \times (base^{10})^{x} res=res×(base10)x。
这样的每次乘幂的次数就降低到 10 10 10以下了,这个乘幂还是有必要二进制快速幂一下,这题卡这个是严了一点。但是这样也避免了全局转二进制太麻烦,而且复杂度也不至于太高。
#define _debug(x) cerr<<#x<<" = "<
#include
using namespace std;
typedef long long ll;
template<typename _Tp, const int MAXMatrixSize>
struct Matrix {
_Tp m[MAXMatrixSize][MAXMatrixSize];
_Tp mod = 0;
Matrix() {
memset(m, 0, sizeof m);
}
Matrix(int _mod) : mod(_mod) {
memset(m, 0, sizeof m);
}
void init1() {
//*this = Matrix(mod);
set(0, 0, 1);
set(1, 1, 1);
// for (int i = 0; i < MAXMatrixSize; i++)
// m[i][i] = 1;
}
inline void set(const int &r, const int &c, const _Tp &v) { this->m[r][c] = v; }
inline _Tp get(const int &r, const int &c) { return this->m[r][c]; }
inline void setMod(const _Tp &_mod) { this->mod = _mod; }
inline Matrix operator*(const Matrix t) {
Matrix res(mod);//= Matrix(mod);
res.setMod(mod);
for (int i = 0; i < MAXMatrixSize; i++)
for (int j = 0; j < MAXMatrixSize; j++)
for (int k = 0; k < MAXMatrixSize; k++)
res.m[i][j] = (res.m[i][j] + m[i][k] * t.m[k][j]) % mod;
return res;
}
};
typedef Matrix<ll, 2> mat;
mat A, B;
ll x0, x1, a, b;
ll mo, len;
char n[1000059];
inline mat fpow(mat base, ll exp) {
mat res(mo);
res.init1();
while (exp) {
if (exp & 1)res = res * base;
exp >>= 1;
base = base * base;
}
return res;
}
inline ll calc() {
len = strlen(n);
//reverse(n, n + len);
mat res(mo);
res.init1();
mat base = B;
for (int i = len - 1; i >= 0; --i) {
if (n[i] > '0')
res = res * fpow(base, n[i] - '0');
base = fpow(base, 10);
}
res = A * res;
return res.get(0, 0);
}
int main() {
scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
scanf("%s %lld", n, &mo);
A = mat(mo);
A.set(0, 0, x0);
A.set(0, 1, x1);
B = mat(mo);
B.set(0, 0, 0);
B.set(0, 1, b);
B.set(1, 0, 1);
B.set(1, 1, a);
printf("%lld\n", calc());
return 0;
}
/*
* */