HDU多校Round 7

Solved:2

rank:293

 

J. Sequense

不知道自己写的什么东西 以后整数分块直接用 n / (n / i)表示一个块内相同n / i的最大i

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll A, B, C, D, P, n;

struct martix
{
    ll c[3][3];
};

martix mul(martix A, martix B)
{
    martix res;
    memset(res.c, 0, sizeof(res.c));
    for(int i = 0; i < 3; i++)
    for(int j = 0; j < 3; j++)
    for(int k = 0; k < 3; k++)
        res.c[i][j] = (res.c[i][j] + A.c[i][k] * B.c[k][j] % mod) % mod, (res.c[i][j] += mod) %= mod;
    return res;
}

martix pow_mod(martix x, ll y)
{
    martix res;
    memset(res.c, 0, sizeof(res.c));
    res.c[0][0] = res.c[1][1] = res.c[2][2] = 1LL;
    while(y)
    {
        if(y & 1) res = mul(res, x);
        x = mul(x, x);
        y >>= 1;
    }
    return res;
}

int main()
{
    martix og;

    int T;
    scanf("%d", &T);
    while(T--)    
    {
        scanf("%lld%lld%lld%lld%lld%lld", &A, &B, &C, &D, &P, &n);
        memset(og.c, 0, sizeof(og.c));
        og.c[0][0] = D + 1;
        og.c[0][1] = C - D;
        og.c[0][2] = -C;
        og.c[1][0] = og.c[2][1] = 1;
        
        
        ll f1 = A;
        ll f2 = B;
        if(n == 1)
        {
            printf("%lld\n", A);
            continue;
        }
        if(n == 2)
        {
            printf("%lld\n", B);
            continue;
        }
        
        if(n <= 50000)
        {
            for(int i = 3; i <= n; i++)
            {
                ll tmp = f1 * C % mod + D * f2 % mod + P / i;
                tmp %= mod;
                f1 = f2;
                f2 = tmp;
            }
            printf("%lld\n", f2);
            continue;
        }
        
        for(int i = 3; i <= 50000; i++)
        {
            ll tmp = f1 * C % mod + D * f2 % mod + P / i;
            tmp %= mod;
            f1 = f2;
            f2 = tmp;
        }
        
        ll now = 50001;
        ll f3 = C * f1 % mod + D * f2 % mod + P / now; f3 %= mod;
        //cout<<f3<<endl;
        ll ans = f3;
        while(now < n)
        {
            if(P / now == P / n)
            {
                ans = 0;
                martix tmp1 = pow_mod(og, n - now);
                ans = tmp1.c[0][0] * f3 % mod + tmp1.c[0][1] * f2 % mod; ans %= mod;
                ans += tmp1.c[0][2] * f1 % mod; ans %= mod;
                ans += mod; ans %= mod;
                break;
            }
            
            if(now + 10000 >= n)
            {
                for(int i = now + 1; i <= n; i++)
                {
                    ll ttmp = f2 * C % mod + D * f3 % mod + P / i;
                    ttmp %= mod;
                    f1 = f2;
                    f2 = f3;
                    f3 = ttmp;
                }
                ans = f3;
                break;
            }
            
            if(P / (now + 1) != P / now)
            {
                for(int i = now + 1; i <= now + 3; i++)
                {
                    ll tymp = f2 * C % mod + D * f3 % mod + P / i;
                    tymp %= mod;
                    f1 = f2;
                    f2 = f3;
                    f3 = tymp;
                }
                now += 3;
                continue;
            }
            
            
            ll l = now, r = n;
            ll mid = l + r >> 1;
            while(l + 1 < r)
            {
                mid = l + r >> 1;
                if(P / mid == P / now) l = mid;
                else r = mid;
            }
            
            ll opp;
            if(P / r == P / now) opp = r;
            else opp = l;
            
            
            if(opp - now >= 5)
            {
                martix tmp2 = pow_mod(og, opp - now - 2);
                ll tt = 0;
                tt = tmp2.c[0][0] * f3 % mod + tmp2.c[0][1] * f2 % mod; tt %= mod;
                tt += tmp2.c[0][2] * f1 % mod; tt %= mod;
                tt += mod; tt %= mod;
                
                tmp2 = mul(tmp2, og);
                ll ttt = 0;
                ttt = tmp2.c[0][0] * f3 % mod + tmp2.c[0][1] * f2 % mod; ttt %= mod;
                ttt += tmp2.c[0][2] * f1 % mod; ttt %= mod;
                ttt += mod; ttt %= mod;
                
                f1 = tt;
                f2 = ttt;
                f3 = C * f1 % mod + D * f2 % mod + P / opp;
                f3 %= mod;
                now = opp;
            }
            else
            {
                for(int i = now + 1; i <= opp; i++)
                {
                    ll tmpp = C * f2 % mod + D * f3 % mod + P / i;
                    tmpp %= mod;
                    f1 = f2;
                    f2 = f3;
                    f3 = tmpp;
                }
                now = opp;
            }
        }
        printf("%lld\n", ans);
    } 
    return 0;
}
View Code

 

posted @ 2018-08-14 23:44  lwqq3  阅读(116)  评论(0编辑  收藏  举报