题目传送门
前置知识
矩阵加速递推
解法
设 \(f_{i}\) 表示将 \(s_{1} \sim s_{i}\) 拼起来后的值,状态转移方程形如 \(f_{i}=10^{k}f_{i-1}+s_{i}\) ,其中 \(k=\left\lfloor \log_{10}s_{i} \right\rfloor+1\) 。
又因为保证等差数列中的元素 \(\le 10^{18}\) ,对于每个 \(k \in [1,19]\) 分别进行矩阵加速递推即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
ll p;
struct Matrix
{ll ma[4][4];Matrix(){memset(ma,0,sizeof(ma));}Matrix operator * (const Matrix another){Matrix ans;for(ll i=1;i<=3;i++){for(ll j=1;j<=3;j++){for(ll h=1;h<=3;h++){ans.ma[i][j]=(ans.ma[i][j]+(ma[i][h]%p)*(another.ma[h][j]%p)%p)%p;}}}return ans;}
}f,Base;
Matrix qpow(Matrix a,ll b)
{Matrix ans;for(ll i=1;i<=3;i++){ans.ma[i][i]=1;}while(b){if(b&1){ans=ans*a;}b>>=1;a=a*a;}return ans;
}
int main()
{
// #define Isaac
#ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout);
#endifll a,b,n,cnt;cin>>n>>a>>b>>p;f.ma[1][1]=0;f.ma[1][2]=a;f.ma[1][3]=1;for(ull i=10;i<=1000000000000000000;i*=10){if(a<=i){cnt=min(n,(ll)ceil(1.0*(i-a)/b));//计算迭代次数n-=cnt;a+=cnt*b;if(cnt>=1){Base.ma[1][1]=i%p;Base.ma[1][2]=0;Base.ma[1][3]=0;Base.ma[2][1]=1;Base.ma[2][2]=1;Base.ma[2][3]=0;Base.ma[3][1]=0;Base.ma[3][2]=b%p;Base.ma[3][3]=1;f=f*qpow(Base,cnt);}}}printf("%lld\n",f.ma[1][1]);return 0;
}