题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2326

题解

分位讨论,记f[i]为Concatenate(1..i)的值,对于k位数

[f[i]i+11]=[f[i1]i1][10k00011001]

分类讨论+矩乘优化dp,细节很难处理。

代码

#include <cstdio>

typedef unsigned long long ull;

int mod;

struct matrix
{
  int n,m,a[3][3];

  matrix(int _n=1,int _m=1)
  {
    n=_n;
    m=_m;
    for(int i=0; i<n; ++i)
      {
        for(int j=0; j<m; ++j)
          {
            a[i][j]=0;
          }
      }
    if(n==m)
      {
        for(int i=0; i<n; ++i)
          {
            a[i][i]=1;
          }
      }
  }

  matrix operator *(const matrix &other) const
  {
    matrix res;
    res.n=n;
    res.m=other.m;
    for(int i=0; i<n; ++i)
      {
        for(int j=0; j<other.m; ++j)
          {
            int ans=0;
            for(int k=0; k<m; ++k)
              {
                ans=(ans+1ll*a[i][k]*other.a[k][j])%mod;
              }
            res.a[i][j]=ans;
          }
      }
    return res;
  }

  int print()
  {
    for(int i=0; i<n; ++i)
      {
        for(int j=0; j<m; ++j)
          {
            printf("%d ",a[i][j]);
          }
        puts("");
      }
    return 0;
  }
};

int quickpow(int a,long long b)
{
  int res=1;
  while(b)
    {
      if(b&1)
        {
          res=1ll*res*a%mod;
        }
      a=1ll*a*a%mod;
      b>>=1;
    }
  return res;
}

matrix quickpow(matrix a,long long b)
{
  matrix res(a.n,a.m);
  while(b)
    {
      if(b&1)
        {
          res=res*a;
        }
      a=a*a;
      b>>=1;
    }
  return res;
}

int ans;
long long n;
matrix st(1,3),trans(3,3);

int main()
{
  scanf("%lld%d",&n,&mod);
  trans.a[1][0]=1;
  trans.a[2][1]=1;
  long long start;
  ull end;
  for(start=1; end=(ull)start*10-1,end<(ull)n; start=end+1)
    {
      st.a[0][0]=start%mod;
      st.a[0][1]=(start+1)%mod;
      st.a[0][2]=1;
      trans.a[0][0]=(end+1)%mod;
      st=st*quickpow(trans,end-start);
      ans=((1ll*ans*quickpow((end+1)%mod,end-start+1))+st.a[0][0])%mod;
    }
  st.a[0][0]=start%mod;
  st.a[0][1]=(start+1)%mod;
  st.a[0][2]=1;
  trans.a[0][0]=(end+1)%mod;
  st=st*quickpow(trans,n-start);
  ans=((1ll*ans*quickpow((end+1)%mod,n-start+1))+st.a[0][0])%mod;
  printf("%d\n",ans);
  return 0;
}