题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6198
思路:先手推出前几项,然后直接套用模板就
o
k
{ok}
ok了。
模板真好用。。。。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
ll qpow(ll x,ll y)
{
ll ans=1;
x%=mod;
while(y){
if(y&1)
ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans;
}
typedef vector<int> VI;
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){
for (int i=0; i<k+k; i++){
c[i]=0;
}
for (int i=0; i<k; i++){
if ( a[i] ){
for (int j=0; j<k; j++){
c[i+j]=(c[i+j] + a[i] * b[j])% mod;
}
}
}
for (int i=k+k-1; i>=k; i--){
if ( c[i] ){
for (int j=0; j < (int)Md.size(); j++){
c[ i-k+Md[j] ] = (c[ i-k+Md[j] ] - c[i] * md[ Md[j] ])%mod;
}
}
}
for (int i=0; i<k; i++){
a[i]=c[i];
}
}
ll solve(ll n, VI a, VI b){
ll ans=0, pnt=0;
int k=(int)a.size();
assert((int)a.size()==(int)b.size());
for (int i=0; i<k; i++){
md[k-1-i]=-a[i];
}
md[k]=1;
Md.clear();
for (int i=0; i<k; i++){
if ( md[i] != 0){
Md.push_back(i);
}
}
for (int i=0; i<k; i++){
res[i] = base[i] = 0;
}
res[0]=1;
while ( ( 1|1 << 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;
for (int j=0; j< (int) Md.size(); j++){
res[ Md[j] ]=(res[ Md[j] ]- res[k] * md[ Md[j] ] )%mod;
}
}
}
for (int i=0; i<k; i++){
ans=( ( ans + res[i] * b[i] )%mod + mod )%mod;
}
return ans;
}
VI BM(VI s){
VI C(1,1), B(1,1);
int L=0, m=1, b=1;
for (int n=0; n<(int)s.size(); n++){
ll d=0;
for (int i=0; i<L+1; i++){
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*qpow( b, mod-2)%mod;
while ((int)C.size() < (int)B.size()+m){
C.push_back(0);
}
for (int i=0; i<(int)B.size(); i++){
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*qpow(b, mod-2)%mod;
while ((int)C.size()<(int)B.size()+m){
C.push_back(0);
}
for (int i=0; i<(int)B.size(); i++){
C[i+m]= ( C[i+m] + c*B[i] )%mod;
}
m++;
}
}
return C;
}
ll gao( VI a, ll n){
VI c=BM( a );
c.erase( c.begin() );
for (int i=0; i<(int)c.size(); i++){
c[i]= ( mod -c[i] )%mod;
}
return solve( n, c, VI( a.begin(), a.begin() + (int)c.size() ) );
}
};
int main()
{
VI a;
int N,v;
a.push_back(4);
a.push_back(12);
a.push_back(33);
a.push_back(88);
a.push_back(232);
a.push_back(609);
a.push_back(1596);
ll n;
while (~scanf("%lld",&n)){
ll ans=linear_seq::gao(a,n-1);
printf("%lld\n",ans);
}
return 0;
}
算法参考:https://zerol.me/2018/02/06/linearly-recurrent-sequence/
我一定可以的!!!