JZ高中OJ 6275. [NOIP提高组模拟1]小L的数列

Description
 
Input
一行两个整数n和k。

之后1行k个正整数b1...bk。

之后1行k个正整数f1...fk。
 
Output
输出一个整数表示fn
 
Sample Input
【样例输入1】

5 4

1 2 3 4

4 3 2 1

【样例输入2】

100000 4

1 2 3 4

12 23 34 45

 
Sample Output
【样例输出1】

27648

样例输出2】

33508797
 
 
Data Constraint
对于30%的数据,n≤10000.

对于另外20%的数据,bi=1,n≤1000000.

对于另外20%的数据,f[1]...f[k-1]=1.

对于另外20%的数据,k≤30.

对于100%的数据,1≤k≤200,1≤n≤40000000,1≤bi,fi≤998244352.
 
 
Hint
样例解释:1*2*2*3*3*3*4*4*4*4=27648
  1 #include <bits/stdc++.h>
  2 #define mod 998244353
  3 #define ll long long
  4 ll n, k;
  5 ll b[205], f[1000005];
  6 ll A[205][205];
  7 ll B[205][205];
  8 ll C[205][205];
  9 
 10 void cf () {
 11     memset (C, 0, sizeof (C));
 12     for (ll i = 1;i <= k;i++) {
 13         for (ll j = 1;j <= k;j++) {
 14             for (ll l = 1;l <= k;l++) {
 15                 C[i][j] += A[l][j] * B[i][l];
 16                 C[i][j] %= (mod - 1);
 17             }
 18         }
 19     }
 20     for (ll i = 1;i <= k;i++) {
 21         for (ll j = 1;j <= k;j++) {
 22             B[i][j] = C[i][j];
 23         }
 24     }
 25     return;
 26 }
 27 void pf () {
 28     memset (C, 0, sizeof (C));
 29     for (ll i = 1;i <= k;i++) {
 30         for (ll j = 1;j <= k;j++) {
 31             for (ll l = 1;l <= k;l++) {
 32                 C[i][j] += A[l][j] * A[i][l];
 33                 C[i][j] %= (mod - 1);
 34             }
 35         }
 36     }
 37     for (ll i = 1;i <= k;i++) {
 38         for (ll j = 1;j <= k;j++) {
 39             A[i][j] = C[i][j];
 40         }
 41     }
 42     return;
 43 }
 44 void ksm (ll y) {
 45     while (y) {
 46         if (y % 2 != 0) {
 47             cf ();
 48         }
 49         pf ();
 50         y >>= 1;
 51     }
 52     return;
 53 }
 54 ll ksm2 (ll x, ll y) {
 55     ll sum = 1;
 56     while (y) {
 57         if (y % 2 > 0) {
 58             sum *= x;
 59             sum %= mod;
 60         }
 61         x *= x;
 62         x %= mod;
 63         y >>= 1;
 64     }
 65     return sum;
 66 }
 67 int main () {
 68     freopen ("seq.in", "r", stdin);
 69     freopen ("seq.out", "w", stdout);
 70     scanf ("%lld %lld", &n, &k);
 71     for (ll i = 1;i <= k;i++) {
 72         scanf ("%lld", &b[i]);
 73     }
 74     for (ll i = 1;i <= k;i++) {
 75         scanf ("%lld", &f[i]);
 76     }
 77     if (n * k <= 100000000) {
 78         for (ll i = k + 1;i <= n;i++) {
 79             f[i] = 1;
 80             for (ll j = 1;j <= k;j++) {
 81                 f[i] *= ksm2 (f[i - j], b[j]);
 82                 f[i] %= mod;
 83             }
 84         }
 85         printf ("%lld", f[n]);
 86         return 0;
 87     }
 88     memset (A, 0, sizeof (A));
 89     for (ll i = 1;i <= k;i++) {
 90         A[1][i] = b[i];
 91         B[1][i] = b[i];
 92     }
 93     for (ll i = 2;i <= k;i++) {
 94         A[i][i - 1] = 1;
 95         B[i][i - 1] = 1;
 96     }
 97     ksm (n - k - 1);
 98     ll ans = 1;
 99     for (ll i = 1;i <= k;i++) {
100         ans *= ksm2 (f[k - i + 1], B[1][i]);
101         ans %= mod;
102     }
103     printf ("%lld", ans);
104     return 0;
105 }

转载于:https://www.cnblogs.com/anbujingying/p/11317135.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值