Loading

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。从小到大枚举即可。

posted @ 2021-05-03 22:02  hyl天梦  阅读(216)  评论(0编辑  收藏  举报