列表

详情


NC15492. Youhane Generator -Real Model-

描述

祝你一发抽到PUR∠( ᐛ 」∠)_(图片来自Twitter@bemanistyle)

优酱最近痴迷于KONMAI某街机音(抽)乐(卡)游戏Music Voltex Heavenly Haven,这个游戏除了可以给人带来爽上天的1600%疾走感之外,最为吸引人的就是可以以60块钱5张的价格抽取现场印刷的真实的卡片。虽然优酱的游戏水平非常低,但这并没有影响她抽卡的热情,毕竟一次性往街机里投60个币同时享受别人看智障的眼神,也是非常有爽快感的。

但是单纯的抽卡并不能满足优酱,她决定建立一个递推模型来量化这种爽快感:给出一个整数表示优酱一共会进行道抽卡,给出一个整数表示每一道抽卡的爽快感会与过去道抽卡的爽快感相关,再给出一个长度的整数向量表示过去道抽卡对当前这一道的影响因子。

我们定义表示第轮抽卡的爽快感,则有:

* 当时,
* 当时,

我们的目标是求出最后一道抽卡的爽快感即的值,由于Music Voltex的爽上天特性,这个爽快感数值可能非常巨大,因此请将其对取模后输出。


输入描述

单文件,多数据,请循环读取到文件末尾。
对于每组数据:
* 第一行为两个整数,用空格分割,含义和范围范围请参见题目描述。
* 第二行为个整数,用空格分割,表示,含义和范围请参见题目描述。
我们保证数据中没有多余不可见字符。

输出描述

对于每组数据,请输出一个整数,表示答案,独占一行。

示例1

输入:

10 3
1 2 3

输出:

4083

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 2883ms, 内存消耗: 616K, 提交时间: 2020-05-01 11:34:30

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;
assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int _,n;
namespace linear_seq {
  const int N=10010;
  ll res[N],base[N],_c[N],_md[N];
  vector<int> Md;
  void mul(ll *a,ll *b,int k) {
    rep(i,0,k+k) _c[i]=0;
    rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
    for (int i=k+k-1;i>=k;i--) if (_c[i])
    rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
    rep(i,0,k) a[i]=_c[i];
  }
  int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
  // printf("%d\n",SZ(b));
    ll ans=0,pnt=0;
    int k=SZ(a);
    assert(SZ(a)==SZ(b));
    rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
    Md.clear();
    rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
    rep(i,0,k) res[i]=base[i]=0;
    res[0]=1;
    while ((1ll<<pnt)<=n) pnt++;
    for (int p=pnt;p>=0;p--) {
      mul(res,res,k);
      if ((n>>p)&1) {
        for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
        rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
      }
    }
    rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
    if (ans<0) ans+=mod;
    return ans;
  }
  VI BM(VI s) {
    VI C(1,1),B(1,1);
    int L=0,m=1,b=1;
    rep(n,0,SZ(s)) {
    ll d=0;
    rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
    if (d==0) ++m;
    else if (2*L<=n) {
      VI T=C;
      ll c=mod-d*powmod(b,mod-2)%mod;
      while (SZ(C)<SZ(B)+m) C.pb(0);
      rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
      L=n+1-L; B=T; b=d; m=1;
    } else {
      ll c=mod-d*powmod(b,mod-2)%mod;
      while (SZ(C)<SZ(B)+m) C.pb(0);
      rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
      ++m;
    }
    }
    return C;
  }
  int gao(VI a,ll n) {
    VI c=BM(a);
    c.erase(c.begin());
    rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
    return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
  }
};
ll kv[1100];
int jc[5100];
int main() {
  int T;
  ll n,k;
  vector<int>v;
  jc[0]=jc[1]=1;
  for(int i=2;i<=5000;i++)jc[i]=1LL*i*jc[i-1]%mod;
  while (scanf("%lld%lld",&n,&k)==2) {
    v.clear();
    for(int i=0;i<k;i++)scanf("%lld",&kv[i]);
    for(int i=0;i<=min(5000LL,n);i++){
      if(i<k)v.push_back(1);
      else{
        int res=1LL*jc[i]*powmod(jc[i-k],mod-2)%mod*powmod(jc[k],mod-2)%mod;

        for(int j=0;j<k;j++){
          res=(res+1LL*kv[j]*v[i-1-j]%mod)%mod;
          //printf(",res=%d,%lld\n",v[i-1-j],kv[i]);
        }
        v.push_back(res);

      }
    }
    printf("%d\n",linear_seq::gao(v,n));
  }
}

C++11(clang++ 3.9) 解法, 执行用时: 3103ms, 内存消耗: 604K, 提交时间: 2019-03-13 01:49:14

#include<bits/stdc++.h>
using namespace std;
const int N = 4e3 + 7;
typedef long long ll;
const int mod = 1e9 + 7;

ll F[N], invF[N];
ll C(int n, int m) {
    if(n < m || m < 0) return 0;
    return F[n] * invF[m] % mod * invF[n - m] % mod;
}
ll power_mod(ll a, ll b) {
    ll ret = 1;
    for(a %= mod; b; b >>= 1, a = a * a % mod)
        if(b & 1) ret = ret * a % mod;
    return ret;
}
int n, k;
ll a[N], b[N], c[N], _c[N], res[N];

void mul(ll *a, ll *b, ll *md, int L) {
    for(int i = 0; i < 2 * L; i++) _c[i] = 0;
    for(int i = 0; i < L; i++)
        for(int j = 0; j < L; j++)
            (_c[i + j] += a[i] * b[j]) %= mod;
    for(int i = 2 * L - 2; i >= L; i--)
        for(int j = 0; j < L; j++)
            (_c[i - j - 1] += _c[i] * md[j]) %= mod;
    for(int i = 0; i < L; i++) a[i] = _c[i];
}

ll solve(ll *res, ll *r, int n, int L) {
    int pn = 0; ll ret = 0;
    while((1<<pn) <= n) pn++; pn--;
    for(int i = 0; i < L; i++) res[i] = 0;
    res[0] = 1;
    for(int i = pn; ~i; i--) {
        mul(res, res, b, L);
        if(n>>i&1) {
            for(int i = L - 1; ~i; i--)
                res[i + 1] = res[i];
            res[0] = 0;
            for(int i = 0; i < L; i++)
                (res[L - 1 - i] += res[L] * b[i]) %= mod;
        }
    }
    for(int i = 0; i < L; i++)
        (ret += r[i] * res[i]) %= mod;
    return ret;
}


int main() {
#ifdef local
    freopen("in.txt", "r", stdin);
#endif
    F[0] = invF[0] = 1;
    for(int i = 1; i < N; i++)
        F[i] = F[i - 1] * i % mod;
    invF[N - 1] = power_mod(F[N - 1], mod - 2);
    for(int i = N - 2; i; i--)
        invF[i] = invF[i + 1] * (i + 1) % mod;

    while(~scanf("%d%d", &n, &k)) {
        for(int i = 1; i <= k; i++) {
            scanf("%lld", a + i);
            if(a[i] < 0) a[i] += mod;
        }
        int m = 2 * k + 1;
        for(int i = 0; i <= m; i++) b[i] = 0;
        int sign = 1;
        for(int i = k - 1; ~i; i--, sign = mod - sign)
            b[i + k] = sign * C(k, i) % mod;
        sign = 1;
        for(int i = k; ~i; i--, sign = mod - sign) {
            ll tt = sign * C(k, i) % mod;
            for(int j = 1; j <= k; j++)
                (b[i + k - j] += tt * a[j]) %= mod;
        }
        b[m - 1] = -1;
        for(int i = m - 1; i; i--)
            b[i] = (b[i - 1] + mod - b[i]) % mod;
        b[0] = (mod - b[0]) % mod;;
        reverse(b, b + m);
        for(int i = 0; i < m; i++) {
            if(i < k) c[i] = 1;
            else {
                c[i] = C(i, k);
                for(int j = 1; j <= k; j++)
                    (c[i] += c[i - j] * a[j]) %= mod;
            }
        }
        printf("%lld\n", solve(res, c, n, m));
    }
    return 0;
}

上一题