题解:
相当于是要求:
然后注意这个 比较小,我们可以对组合数分治递归为左边选多少个,右边选多少个,然后卷积起来。 这样而且刚好能把所有 的情况考虑到。时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
int mod;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (long long)x*y%mod;}
namespace FFT {
#define double long double
const int N=1e6+50;
const double PI2=acos(-1.0)*2.0;
int pos[N],k;
struct CP {
double r,i;
CP() {}
CP(double r,double i) : r(r),i(i) {}
friend inline CP operator *(const CP &a,const CP &b) {return CP(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);}
friend inline CP operator +(const CP &a,const CP &b) {return CP(a.r+b.r,a.i+b.i);}
friend inline CP operator -(const CP &a,const CP &b) {return CP(a.r-b.r,a.i-b.i);}
} A[N],B[N],w[N];
inline void dft(CP *a) {
for(int i=1;i<k;i++)
if(pos[i]>i) swap(a[pos[i]],a[i]);
for(int bl=1;bl<k;bl<<=1) {
int tl=bl<<1; CP wn=CP(cos(PI2/tl),sin(PI2/tl));
w[0]=CP(1,0); for(int i=1;i<bl;i++) w[i]=w[i-1]*wn;
for(int bg=0;bg<k;bg+=tl)
for(int j=0;j<bl;j++) {
CP &t1=a[bg+j], &t2=a[bg+j+bl], t=t2*w[j];
t2=t1-t; t1=t1+t;
}
}
}
inline void init(int n) {
for(k=1;k<=n;k<<=1);
for(int i=1;i<k;i++)
pos[i]=(i&1) ? ((pos[i>>1]>>1)^(k>>1)) : (pos[i>>1]>>1);
for(int i=0;i<k;i++) A[i]=B[i]=CP(0,0);
}
inline void func() {
dft(A); dft(B);
for(int i=0;i<k;i++) A[i]=A[i]*B[i];
dft(A); reverse(A+1,A+k);
for(int i=0;i<k;i++) A[i].r/=k;
}
#undef double
}
int n,A,ans;
struct poly {
vector <int> a;
poly(int d=0,int t=0) {a.resize(d+1); a[d]=t;}
inline int deg() const {return a.size()-1;}
inline int& operator[](const int &i) {return a[i];}
inline const int& operator[](const int &i) const {return a[i];}
friend inline poly operator +(const poly &a,const poly &b) {
poly c(max(a.deg(),b.deg()),0);
for(int i=0;i<=a.deg();i++) c[i]=add(c[i],a[i]);
for(int i=0;i<=b.deg();i++) c[i]=add(c[i],b[i]);
return c;
}
friend inline poly operator *(const poly &a,const poly &b) {
poly c(a.deg()+b.deg());
if(a.deg()>20 && b.deg()>20) {
FFT::init(c.deg());
for(int i=0;i<=a.deg();i++) FFT::A[i].r=a[i];
for(int i=0;i<=b.deg();i++) FFT::B[i].r=b[i];
FFT::func();
for(int i=0;i<=c.deg();i++) {
c[i]=((long long)(FFT::A[i].r+0.1))%mod;
assert(c[i]>=0 && c[i]<mod);
}
} else {
for(int i=0;i<=b.deg();i++)
for(int j=0;j<=a.deg();j++)
c[i+j]=add(c[i+j],mul(a[j],b[i]));
}
if(c.deg()>=n) c.a.resize(n); return c;
}
inline int get_sum() {
int t=0;
for(int i=0;i<n && i<=deg();i+=2) t=add(t,a[i]);
return t;
}
};
struct mat {
poly a[2][2];
mat(int t) {
if(t==1) {
a[0][0]=poly(0,1);
a[1][1]=poly(1,1);
a[1][1].a[0]=1;
}
}
friend inline mat operator *(const mat &a,const mat &b) {
mat c(0);
for(int i=0;i<=1;++i)
for(int j=0;j<=1;++j)
for(int k=0;k<=1;k++)
c.a[i][j^k]=c.a[i][j^k]+a.a[1][j]*b.a[i][k];
for(int k=0;k<=1;k++)
c.a[0][k]=c.a[0][k]+a.a[0][k];
return c;
}
};
inline mat solve(int T,int flag) {
if(T==1) {
if(flag) ans=add(ans,1);
return mat(1);
}
if(T&1) {
mat tp=solve(T-1,0)*mat(1);
if(flag) ans=add(ans,tp.a[0][0].get_sum());
return tp;
} else {
mat tp=solve(T/2,1);
tp=tp*tp;
if(flag) ans=add(ans,tp.a[0][0].get_sum());
return tp;
}
}
int main() {
cin>>n>>A>>mod;
mat a(1);
solve(A,0);
cout<<ans<<'\n';
}