HDU4686 Arc of Dream 大力推式子
推一推式子,发现的形式如下,同理:
那么有两种,有两种,直接分4类讨论计算即可。实际上是3类,因为等价。
然而求逆元是的。
也有矩阵加速的做法,但是慢。
然后就hdu rank5 了。rk1~rk10都是15ms。
CODE
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
typedef long long LL;
LL N, n, A0, AX, AY, B0, BX, BY;
inline LL qpow(LL a, LL b) {
LL re = 1;
while(b) {
if(b&1) re = re * a % mod;
a = a * a % mod; b >>= 1;
}
return re;
}
inline void add(LL &x, LL y) { x = (x + y) % mod; }
inline LL calc(LL x, LL m) { return (qpow(x, m+1) - x) % mod * qpow(x-1, mod-2) % mod; }
inline LL solve(LL x, LL m) {
return (m * qpow(x, m+1) % mod - calc(x, m)) % mod * qpow(x-1, mod-2) % mod;
}
int main () {
LL inv2 = qpow(2, mod-2);
LL inv6 = qpow(6, mod-2);
while(~scanf("%lld%lld%lld%lld%lld%lld%lld", &N, &A0, &AX, &AY, &B0, &BX, &BY)) {
if(!N) { puts("0"); continue; }
if(N == 1) { printf("%lld\n", (A0 * B0 % mod + mod) % mod); continue; }
--N;
A0 %= mod; AX %= mod; AY %= mod;
B0 %= mod; BX %= mod; BY %= mod;
n = N % mod;
LL ans = A0 * B0 % mod;
if(AX == 1 && BX == 1) {
add(ans, AY * BY % mod * n % mod * (n+1) % mod * (2*n+1) % mod * inv6 % mod);
add(ans, (B0 * AY % mod + A0 * BY % mod) % mod * n % mod * (n+1) % mod * inv2 % mod);
add(ans, A0 * B0 % mod * n % mod);
}
else if(AX != 1 && BX != 1) {
LL A1 = AY * qpow((1-AX) % mod, mod-2) % mod, A2 = (A0 - A1) % mod;
LL B1 = BY * qpow((1-BX) % mod, mod-2) % mod, B2 = (B0 - B1) % mod;
add(ans, A1 * B1 % mod * n % mod);
add(ans, A1 * B2 % mod * calc(BX, N) % mod);
add(ans, A2 * B1 % mod * calc(AX, N) % mod);
add(ans, A2 * B2 % mod * calc(AX*BX%mod, N) % mod);
}
else {
if(AX != 1) {
swap(AX, BX);
swap(A0, B0);
swap(AY, BY);
}
//AX = 1
LL B1 = BY * qpow((1-BX) % mod, mod-2) % mod, B2 = (B0 - B1) % mod;
add(ans, AY * B1 % mod * n % mod * (n+1) % mod * inv2 % mod);
add(ans, A0 * B1 % mod * n % mod);
add(ans, A0 * B2 % mod * calc(BX, N) % mod);
add(ans, AY * B2 % mod * solve(BX, N) % mod);
}
printf("%lld\n", (ans + mod) % mod);
}
}