5.3
1考试题解
第一题
递推式:\(f_{i+1}=x*f_i+i+1\)
在mod p意义下,因为可能不存在逆元,所以无法用通项公式计算。加速递推,在无法算出通项公式的情况下,我们考虑加速递推。
目前,只学过矩阵加速递推。
\((f_i,i,1)\)到\((f_{i+1},i+1,1)\),考虑构造一个\(3\times 3\)矩阵使得矩阵乘法满足上面式子的递推形式。
构造可得:
\[\begin{pmatrix}x&0&0\\1&1&0\\1&1&1\end{pmatrix}
\]
利用矩阵快速幂可以得到。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ld long double
#define ll long long
#define int long long
#define ull unsigned long long
#define N number
#define M number
using namespace std;
const int INF=0x3f3f3f3f;
template <typename T> inline void read(T &x) {
x=0; int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
x*=f;
}
template <typename T> inline void write(T x) {
if(x < 0) x=-x,putchar('-');
if(x > 9) write(x / 10);
putchar(x%10+'0');
}
template <typename T> inline void writeln(T x) {
write(x);
puts("");
}
struct matrix{
int a[4][4],n,m;
inline matrix(){
memset(a,0,sizeof(a));n=m=1;
}
inline void dwh(int x){
n=m=x;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++) a[i][i]=1;
}
inline void print(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) printf("%d ",a[i][j]);
puts("");
}
puts("");
}
};
int n,x,p;
inline matrix operator * (const matrix &a,const matrix &b){
matrix c;
c.n=a.n;c.m=b.m;
for(int i=1;i<=a.n;i++)
for(int j=1;j<=b.m;j++)
for(int k=1;k<=a.m;k++) (c.a[i][j]+=a.a[i][k]*b.a[k][j]%p)%=p;
return c;
}
matrix m,fir;
inline void prework(){
m.a[1][1]=x;
m.a[2][1]=m.a[3][1]=m.a[2][2]=m.a[3][2]=m.a[3][3]=1;
fir.a[1][1]=fir.a[1][2]=fir.a[1][3]=1;
m.n=m.m=3;
fir.n=1;fir.m=3;
}
inline matrix ksm(matrix a,int b){
matrix res;res.dwh(a.n);
while(b){
if(b&1) res=res*a;
a=a*a;
b>>=1;
}
return res;
}
signed main(){
read(n);read(x);read(p);
prework();
m=ksm(m,n-1);
fir=fir*m;
write(fir.a[1][1]);
return 0;
}
第二题
80分做法
设\(f_{i,j}\)表示位数为i,\(\mod k\)时余数为j时的最小数为多少。
我们从小到大枚举。
100分做法
实际上可以以每一个点作为mod k余下j的最小整数,bfs一遍即可。
第三题
通过简单地鸽巢原理可以发现,字符串最长不到20
所以我们提前处理处所有长度小于20的字符串有没有出现过,用dp。从小到大枚举即可。