51Nod-1197-字符串的数量 V2

来源:互联网 发布:大数据信息化调研提纲 编辑:程序博客网 时间:2024/04/27 23:17

ACM模版

描述

描述

题解

这道题好阔怕,在V1的讨论区有最牛逼的题解,Orz!!!

虽然有题解,有代码,可是由于代数还没有学,所以对部分有些懵逼,先Mark一下,过一阵子能力有所提升后好好瞅瞅喽……

提供两份代码,对于这道题,代码One和代码Two效率差距不明显,代码Two相比代码One多了一个预处理,针对V3的多组数据可以提高很多效率!!!

代码

One:

#include <stdio.h>typedef long long ll;const int MAXN = 61;const int MOD = 1e9 + 7;int deg;int iact[MAXN + 1];int val[MAXN + 1];int nxt[MAXN + 1];int seq[MAXN + 1];ll n, m;inline int mod_add(int x, int y){    return x + y < MOD ? x + y : x + y - MOD;}inline int mod_dec(int x, int y){    return x - y >= 0 ? x - y : x - y + MOD;}int value(int a){    if (a < deg)    {        return val[a];    }    static int pre[MAXN], suf[MAXN];    pre[0] = a;    for (int i = 1; i < deg; ++i)    {        pre[i] = (ll)(a - i) * pre[i - 1] % MOD;    }    suf[deg - 1] = a - deg + 1;    for (int i = deg - 2; i >= 0; --i)    {        suf[i] = (ll)(a - i) * suf[i + 1] % MOD;    }    int ret = 0;    for (int i = 0; i < deg; ++i)    {        int tmp = (ll)val[i] * iact[i] % MOD * iact[deg - 1 - i] % MOD;        if (i > 0)        {            tmp = (ll)tmp * pre[i - 1] % MOD;        }        if (i < deg - 1)        {            tmp = (ll)tmp * suf[i + 1] % MOD;        }        if (((deg - 1 - i) & 1) && tmp > 0)        {            tmp = MOD - tmp;        }        ret += tmp;        if (ret >= MOD)        {            ret -= MOD;        }    }    return ret;}struct Matrix{    int r, c, num[MAXN][MAXN];    Matrix operator * (const Matrix &t) const    {        Matrix ret = {r, t.c};        for (int i = 0; i < r; ++i)        {            for (int j = 0; j < c; ++j)            {                for (int k = 0; k < t.c; ++k)                {                    ret.num[i][k] = (ret.num[i][k] + (ll)num[i][j] * t.num[j][k]) % MOD;                }            }        }        return ret;    }    Matrix pow(ll k)    {        Matrix ret = {r, r}, tmp = *this;        for (int i = 0; i < r; ++i)        {            ret.num[i][i] = 1;        }        for (; k > 0; k >>= 1, tmp = tmp * tmp)        {            if (k & 1)            {                ret = ret * tmp;            }        }        return ret;    }} A;int main(){//    int T;//    scanf("%d", &T);//    while (T--)//    {        iact[0] = 0;        iact[1] = 1;        for (int i = 2; i <= MAXN; ++i)        {            iact[i] = MOD - MOD / i * (ll)iact[MOD % i] % MOD;        }        iact[0] = 1;        for (int i = 1; i <= MAXN; ++i)        {            iact[i] = iact[i - 1] * (ll)iact[i] % MOD;        }        int len;        scanf("%lld%lld", &n, &m);        ll tmp = (n << 1) - 1;        deg = val[0] = 1;        for (len = 1; --tmp >= 0; ++len)        {            for (int i = 0, pos = tmp & 1; i <= deg; ++i, pos = mod_add(pos, 2))            {                nxt[i] = mod_add(i > 0 ? nxt[i - 1] : 0, value(pos));            }            ++deg;            for (int i = 0; i < deg; ++i)            {                val[i] = nxt[i];            }            tmp >>= 1;            seq[len] = value(tmp % MOD);        }        --len;        ll tmp_ = n - 1;        deg = val[0] = 1;        for (int j = 1; --tmp_ >= 0; ++j)        {            for (int i = 0, pos = tmp_ & 1; i <= deg; ++i, pos = mod_add(pos, 2))            {                nxt[i] = mod_add(i > 0 ? nxt[i - 1] : 0, value(pos));            }            ++deg;            for (int i = 0; i < deg; ++i)            {                val[i] = nxt[i];            }            tmp_ >>= 1;            seq[j] = mod_dec(seq[j], value(tmp_ % MOD));        }        A = (Matrix){len, len};        for (int i = 1; i < len; ++i)        {            A.num[i][i - 1] = 1;        }        for (int i = 0; i < len; ++i)        {            A.num[i][len - 1] = seq[len - i];        }        A = A.pow(m);        printf("%d\n", A.num[len - 1][len - 1]);//    }    return 0;}

Two:

#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>using namespace std;typedef long long ll;const int MOD = 1e9 + 7;const int MAXN = 63;void add(ll &x, ll y){    x += y;    if (x >= MOD)    {        x -= MOD;    }}ll i, j;ll p, k;ll MAXP;ll A[MAXN + 5][MAXN + 5];ll E[MAXN + 5];ll pr[20005];ll MA[20005];vector<ll> v[MAXN];vector<ll> va[MAXN];vector<ll> vb[MAXN];vector<ll> vr[MAXN];ll modAdd(ll a, ll b){    a += b;    return a >= MOD ? (a - MOD) : a;}ll modMul(ll a , ll b){    a *= b;    return a >= MOD ? (a % MOD) : a;}void multiply(const vector<ll> &Q, vector<ll> &Qr){    int size = (int)Qr.size();    for (int i = 0 ; i < size; i++)    {        Qr[i] = 0;        for (int j = max(0 , 2 * i - size + 1); j < min(size, (2 * i + 1)); j++)        {            ll x = (j & 1) ? ((MOD - Q[j])) : (Q[j]);            ll y = modMul(x, Q[2 * i - j]);            Qr[i] = modAdd(Qr[i], y);        }    }}void cal(ll *A, ll n, ll k, ll *C){    vector<ll> Q(k + 3);    vector<ll> Qr(k + 3);    n--;    while (n >= k)    {        Q[0] = 1;        for (ll i = 0; i < k; i++)        {            Q[i + 1] = -C[i];            if (Q[i + 1] < 0)            {                Q[i + 1] += MOD;            }        }        for (ll i = k; i < (2 * k); i++)        {            A[i] = 0;            for (ll j = 0; j < k; j++)            {                ll add = modMul(A[i - 1 - j], C[j]);                A[i] = modAdd(A[i], add);            }        }        multiply(Q, Qr);        for (ll i = 0; i < k; i++)        {            C[i] = (-Qr[i + 1]);            if (C[i] < 0)            {                C[i] += MOD;            }        }        int offset = n & 1;        for (ll i = 0; i < k; i++)        {            A[i] = A[2 * i + offset];        }        n /= 2;    }    printf("%lld\n", A[n]);}int power(ll x, ll y){    int sum = 1;    for (; y; y >>= 1)    {        if (y & 1)        {            sum = 1ll * sum * x % MOD;        }        x = 1ll * x * x % MOD;    }    return sum;}void guass(ll n){    for (int i = 1; i <= n; ++i)    {        int j;        for (j = i; j <= n; ++j)        {            if (A[j][i])            {                break;            }        }        for (int k = 1; k <= n + 1; ++k)        {            swap(A[i][k], A[j][k]);        }        int p = power(A[i][i], MOD - 2);        for (int j = i + 1; j <= n; ++j)        {            if (A[j][i])            {                int now = 1ll * A[j][i] * p % MOD;                for (int k = i; k <= n + 1; ++k)                {                    add(A[j][k], MOD - 1ll * A[i][k] * now % MOD);                }            }        }    }    for (ll i = n; i; --i)    {        for (ll j = i + 1; j <= n; ++j)        {            add(A[i][n + 1], MOD - 1ll * A[i][j] * E[j] % MOD);        }        E[i] = 1ll * A[i][n + 1] * power(A[i][i], MOD - 2) % MOD;    }}long long n, m, sA[MAXN], sB[MAXN];long long Count(vector<ll> A, ll R){    ll i, j, sum = 0;    R %= MOD;    for (i = 0; i < A.size(); ++i)    {        ll S = 0, now = 1;        for (j = 0; j < vr[i].size(); ++j)        {            add(S, 1ll * vr[i][j] * now % MOD), now = 1ll * now * R % MOD;        }        add(sum, 1ll * S * A[i] % MOD);    }    return sum;}int main(){    for (i = 0; i < MAXN; ++i)    {        memset(A, 0, sizeof(A));        for (j = 1; j <= i + 2; ++j)        {            for (k = 1; k <= i + 2; ++k)            {                A[j][k] = power(j, k - 1);            }            A[j][i + 3] = power(2 * j - 1, i);            add(A[j][i + 3], A[j - 1][i + 3]);            if (j > 1)            {                add(A[j][i + 3], power(2 * j - 2, i));            }        }        guass(i + 2);        for (j = 1; j <= i + 2; ++j)        {            v[i].push_back(E[j]);        }    }    for (i = 0; i < MAXN; ++i)    {        memset(A, 0, sizeof(A));        for (j = 1; j <= i + 2; ++j)        {            for (k = 1; k <= i + 2; ++k)            {                A[j][k] = power(j, k - 1);            }            A[j][i + 3] = power(j, i);            (A[j][i + 3] += A[j - 1][i + 3]) %= MOD;        }        guass(i + 2);        for (j = 1; j <= i + 2; ++j)        {            vr[i].push_back(E[j]);        }    }//    int T;//    scanf("%d", &T);//    for (; T--; )//    {        scanf("%lld%lld", &n, &m);        MAXP = (int)(log2(n) + 1);        memset(sA, 0, sizeof(sA));        memset(sB, 0, sizeof(sB));        for (i = 1; i <= MAXP; ++i)        {            va[i].clear(), vb[i].clear();        }        sA[1] = n / 2;        sB[1] = n;        vb[1].push_back(1);        for (i = 2; i <= MAXP; ++i)        {            sA[i] = sA[i - 1] / 2;            sB[i] = sB[i - 1] / 2;            long long str = Count(vb[i - 1], sB[i - 1]);            for (j = 0; j < i; ++j)            {                vb[i].push_back(0), va[i].push_back(0);            }            vb[i][0] = str;            for (j = 0; j < vb[i - 1].size(); ++j)            {                ll wei = (MOD - vb[i - 1][j]);                for (k = 0; k < (int)v[j].size(); ++k)                {                    add(vb[i][k], 1ll * wei * v[j][k] % MOD);                }            }            ll End = Count(vb[i - 1], sA[i - 1]);            va[i][0] = (str - End + MOD) % MOD;            add(va[i][0], Count(va[i - 1], sA[i - 1]));            for (j = 0; j < va[i - 1].size(); ++j)            {                ll wei = (MOD - va[i - 1][j]);                for (k = 0; k < v[j].size(); ++k)                {                    add(va[i][k], 1ll * wei * v[j][k] % MOD);                }            }        }        for (i = 1; i <= MAXP; ++i)        {            pr[i] = Count(va[i], sA[i]);            add(pr[i], Count(vb[i], sB[i]));            add(pr[i], MOD - Count(vb[i], sA[i]));        }        memset(MA, 0, sizeof(MA));        MA[0] = 1;        for (i = 1; i < MAXP; ++i)        {            for (j = 1; j <= i; ++j)            {                add(MA[i], 1ll * MA[i - j] * pr[j] % MOD);            }        }        for (i = 0; i < MAXP; ++i)        {            swap(pr[i], pr[i + 1]);        }        if (m < MAXP)        {            printf("%lld\n", MA[m]);        }        else        {            cal(MA, m + 1, MAXP, pr);        }//    }    return 0;}

参考

51Nod 1196 字符串的数量

0 0
原创粉丝点击