Hdu 4695 线性递推模版(m^2logn)

来源:互联网 发布:linux找不到mysql命令 编辑:程序博客网 时间:2024/05/29 16:29
#include <bits/stdc++.h>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long ll;#define LL long longconst int mod=1e9+7;const int MOD=1e9+7;const int MAXN=205;ll n;int u, d;int a[100], b[100];ll dp[205];ll A[205];ll C[205];// given first m a[i] and coef (0 based)// calc a[n] % MOD in O(m*m*log(n))// a[n] = sum(c[m - i] * a[n - i]) i = 1....m// a[m] = sum(c[i] * a[i]), i = 0.....m-1LL linear_recurrence(LL n, int m, LL a[], LL c[], int p){ //n->a[i], m -> c[i]    LL v[MAXN] = {1 % MOD}, u[MAXN << 1], msk = !!n;    for(LL i = n; i > 1; i >>= 1) msk <<= 1;    for(LL x = 0; msk; msk >>= 1, x <<= 1){        fill_n(u, m << 1, 0);        int b = !!(n & msk); x |= b;        if(x < m) u[x] = 1 % p;        else{            for(int i = 0; i < m; i++){                for(int j = 0, t = i + b; j < m; ++j, ++t)                    u[t] = (u[t] + v[i] * v[j]) % MOD;            }            for(int i = (m << 1) - 1; i >= m; --i){                for(int j = 0, t = i - m; j < m; ++j, ++t){                    u[t] = (u[t] + c[j] * u[i]) % MOD;                }            }        }        copy(u, u+m, v);    }    LL ans = 0;    for(int i = 0; i < m; i++){        ans = (ans + v[i] * a[i]) % MOD;    }    return ans;}bool vis[205];int main(){    while(~scanf("%lld", &n)){        int ma=0;        memset(dp, 0, sizeof(dp));        memset(A, 0, sizeof(A));        memset(C, 0, sizeof(C));        memset(vis, false, sizeof(vis));        scanf("%d", &u);        for(int i=1;i<=u;i++){scanf("%d", &a[i]);}        scanf("%d", &d);        for(int i=1;i<=d;i++){scanf("%d", &b[i]);ma=max(b[i], ma);vis[b[i]]=true;}        dp[0]=1;        for(int i=1;i<=ma;i++){            for(int j=1;j<=u;j++){                if(i<a[j])continue;                dp[i]=(dp[i-a[j]]+dp[i])%mod;            }        }        vis[0]=true;        for(int i=0;i<=ma;i++)if(!vis[i])dp[i]=0;        for(int i=0;i<ma;i++){C[i]=dp[ma-i];}        A[0]=1;        for(int i=1;i<ma;i++){            for(int j=1;j<=i;j++){                A[i]=(A[i]+A[i-j]*dp[j])%mod;            }        }        ll ans=linear_recurrence(n, ma, A, C, mod);        printf("%lld\n", ans);    }}
原创粉丝点击