递推复习(3)

偶数个3

Desciption

编程求出所有的 n 位数中,有多少个数中有偶数个数字 3。

Input

一行一个正整数 n,0<n<1000。

Output

一行一个正整数,表示 n 位数中有多少个数有偶数个 3。最后答案为12345取模

Sample Input

2

Sample Output

73

Analysis

这一道题的话你要记录两个,奇数有多少个,偶数有多少个。最后实际上经过大量的数据来进行运算(WYX大佬与我一起进行的),我们发现了规律实际上因为我们最开始把1位数那里的偶数个数量设置为9,所以得出来的式子很复杂。
实际就这么想:
偶数个三,再取一位有9个选择,再加上奇数个三,最后只可以取三,1个选择,所以式子就比较明了了

Code

#include<bits/stdc++.h>
#define maxi 1007
#define Mod 12345
using namespace std;
int f[maxi][2];
/*
*后面的,0表示奇数,1表示偶数 
*/
int n;
int main(){
	scanf("%d",&n);
	f[1][1]=8;f[1][0]=1;
	for(int i=2;i<=n;i++){
		f[i][0]=(9*f[i-1][0]+f[i-1][1])%Mod;
		f[i][1]=(9*f[i-1][1]+f[i-1][0])%Mod; 
	}
	cout<<f[n][1];
}

斐波那契前N项和

**Desctiption

求斐波那契数列前n项和取模m

Input

一行两个整数n m

Outpuw

输出前n项和取模m

Sample Input

5 100

Sample Output

12

Analysis

因为数据范围很大,我在这没有给出,但是很明确地,要用long long 以及矩阵快速幂,考虑构造的矩阵为

\[\begin{bmatrix} 1 &0 & 0\\ 1 &1 & 1\\ 1& 1 & 0 \end{bmatrix} \]

而另外一个矩阵则是

\[\begin{bmatrix} 2 &1 &1\\ \end{bmatrix} \]

这是他们初始的状态,解释一下,下面的矩阵第一个数就是我们要求的答案,第二个数就是此时的斐波拉契数,第三个则是前面的一个斐波拉契数

因此可以得到代码

Code

#include<bits/stdc++.h>
#define Int64 long long
using namespace std;

Int64 A[3][3];
Int64 mod,n;

void mul(Int64 *f,Int64 (*t)[3]){
	Int64 tmp[3];
	memset(tmp,0,sizeof(tmp));
	for(int i=0;i<=2;i++){
		for(int k=0;k<=2;k++){
			(tmp[i]+=f[k]*t[k][i])%=mod;
		} 
	}
    for(int i=0;i<=2;i++)f[i]=tmp[i];
	return ;
}

void mulsel(Int64 (*f)[3]){
	Int64 tmp[3][3];
	memset(tmp,0,sizeof(tmp));
	for(int i=0;i<=2;i++){
		for(int j=0;j<=2;j++){
			for(int k=0;k<=2;k++){
				(tmp[i][j]+=f[i][k]*f[k][j])%=mod;
			}
		}
	}
	for(int i=0;i<=2;i++){
		for(int j=0;j<=2;j++)f[i][j]=tmp[i][j];
	}
	return;
}

void qkpow(Int64 b){
	Int64 ans[3]={2,1,1};
	while(b){
		if(b&1){
			mul(ans,A);
		}
		mulsel(A);
		b>>=1;
	}
	printf("%lld",ans[0]);
}

int main(){
	scanf("%lld%lld",&n,&mod);
	A[0][0]=1;A[0][1]=0;A[0][2]=0;
	A[1][1]=1;A[1][0]=1;A[1][2]=1;
	A[2][0]=1;A[2][1]=1;A[2][2]=0;
	if(n==1)cout<<1;
	else if(n==2)cout<<2;
	else qkpow(n-2);
	
	return 0;
}
posted @ 2019-02-17 18:08  Perisino  阅读(272)  评论(2编辑  收藏  举报