HDU4686 Arc of Dream 大力推式子

推一推式子,发现aa的形式如下,bb同理:

an={A0+nAY,AX=1AY1AX+(A0AY1AX)BXn,AX≠1a_n=egin{cases}A0+n*AY,&AX=1\frac{AY}{1-AX}+(A0-frac{AY}{1-AX})*BX^n,&AX= ot1end{cases}

那么aa有两种,bb有两种,直接分4类讨论O(1)O(1)计算即可。实际上是3类,因为a,ba,b等价。

然而求逆元是O(log)O(log)的。

也有矩阵加速的做法,但是慢。

然后就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
", (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
", (ans + mod) % mod);
	}
}

原文地址:https://www.cnblogs.com/Orz-IE/p/12039244.html