题面
给定
n
,
p
,
k
,
r
n,p,k,r
n,p,k,r ,求
∑
i
=
0
∞
C
n
k
i
k
+
r
m
o
d
p
\sum_{i=0}^{\infin}C_{nk}^{ik+r} mod p
i=0∑∞Cnkik+rmodp
n
≤
1
0
9
n\le 10^9
n≤109,
r
<
k
≤
50
r<k\le 50
r<k≤50,
2
≤
p
≤
2
30
−
1
2\le p\le 2^{30}-1
2≤p≤230−1
题解
看数据范围发现大概率是矩阵乘。
C有一个递推式, C m n = C m − 1 n + C m − 1 n − 1 C_{m}^{n}=C_{m-1}^{n}+C_{m-1}^{n-1} Cmn=Cm−1n+Cm−1n−1
设 f ( k , r , l ) = ∑ i = 0 ∞ C l i k + r f(k,r,l)=\sum_{i=0}^{\infin}C_{l}^{ik+r} f(k,r,l)=∑i=0∞Clik+r
则 f ( k , r , l ) = ∑ i = 0 ∞ C l i k + r f(k,r,l)=\sum_{i=0}^{\infin}C_{l}^{ik+r} f(k,r,l)=i=0∑∞Clik+r = ∑ i = 0 ∞ ( C l − 1 i k + r + C l − 1 i k + r − 1 ) =\sum_{i=0}^{\infin}(C_{l-1}^{ik+r}+C_{l-1}^{ik+r-1}) =i=0∑∞(Cl−1ik+r+Cl−1ik+r−1) = f ( k , r , l − 1 ) + f ( k , ( r − 1 + k ) % k , l − 1 ) =f(k,r,l-1)+f(k,(r-1+k)\%k,l-1) =f(k,r,l−1)+f(k,(r−1+k)%k,l−1)
得出这个递推式就很容易矩阵乘了。
感觉这题不应该紫题。。我调一些蓝题的时间都比这题长
放代码:
# include <bits/stdc++.h>
using namespace std;
namespace fastio{
template<typename tn> void read(tn &a){
tn x=0,f=1;char c=' ';
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar() ) x=x*10+c-'0';
a=x*f;
}
template<typename tn> void print(tn a){
if(a<0) putchar('-'),a=-a;
if(a>9) print(a/10);
putchar(a%10+'0');
}
};
using namespace fastio;
const int N=55;
#define int long long
int n,p,k,r;
int f[N],a[N][N];
void mul(int f[N],int a[N][N]){
int c[N];
memset(c,0,sizeof(c));
for(int j=0;j<k;j++)
for(int h=0;h<k;h++)
c[j]=(c[j]+(long long)f[h]*a[h][j])%p;
memcpy(f,c,sizeof(c));
}
void mulself(int a[N][N]){
int c[N][N];
memset(c,0,sizeof(c));
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
for(int h=0;h<k;h++)
c[i][j]=(c[i][j]+(long long)a[i][h]*a[h][j])%p;
memcpy(a,c,sizeof(c));
}
signed main(){
read(n);
read(p);
read(k);
read(r);
for(int i=0;i<k;i++) a[i][i]++,a[i][(i+1)%k]++;
f[0]=1;
long long l=n*k;
for(;l;l>>=1){
if(l&1) mul(f,a);
mulself(a);
}
print(f[r]);
return 0;
}
中间WA了两次:
- 要开long long
- k=1时有一个特判,可以直接把=1改成++