递推复习(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;
}

转载于:https://www.cnblogs.com/perisino/p/10392074.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值