2019 Niuke Summer Multi-School Training Camp (Fifth) B generator 1 [Decimal matrix fast power]

Title description

You are given four positive integers x_0,x_1,a,b . And you know x_i=a\cdot x_i_-_1+b\cdot x_i_-_2​ for all i \ geq 2 .

Given two positive integers n, and MOD, please calculate x_n​ modulo MOD.

Does the problem look simple? Surprise! The value of n may have many many digits!

Enter description 

The input contains two lines.
The first line contains four integers x_0,x_1,a,b (1\leq x_0,x_1,a,b\leq 10^9).
The second line contains two integers n, MOD (1\leq n< 10^(^1^0^^^6^),10^9< MOD\leq 2\times 10^9, n has no leading zero).

Output description 

Print one integer representing the answer.

 Example input 1

1 1 1 1
10 1000000001

Example output 1 

89

Explanation 

The resulting sequence x is Fibonacci sequence. The 11-th item is 89.

Example input 2 

1315 521 20185 5452831
9999999999999999999999999999999999999 1000000007

Sample output 2 

914730061

The main idea:

Given the starting term and recursive formula, the value of the nth term MOD is required.

analysis:

There are starting terms and recursive formulas. It is easy to think of the matrix fast power, but here n is very large. If you use a binary matrix fast power, it will definitely time out, and if you consider decimal, 10^6the complexity is okay.

See the code for specific explanation.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>

#define ll long long
#define INF 0x3f3f3f3f
#define N 2

using namespace std;

const int maxn=1000005;

ll mod;
char str[maxn];

struct mat{
    ll m[N+1][N+1];
};
mat mul(mat a,mat b){
    mat ans;
    int i,j,k;
    for(i=1;i<=N;i++)
        for(j=1;j<=N;j++)
            ans.m[i][j]=0;
    for(i=1;i<=N;i++)
        for(j=1;j<=N;j++)
            for(k=1;k<=N;k++)
                ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j]+mod)%mod;
    return ans;
}

mat matqp(ll p,mat t){//二进制矩阵快速幂,此题不可用 
    mat ans;
    int i,j;
    for(i=1;i<=N;i++)
        for(j=1;j<=N;j++)
            if(i==j)ans.m[i][j]=1;
            else ans.m[i][j]=0;
    while(p)
    {
        if(p&1)
            ans=mul(ans,t);
        t=mul(t,t);
        p=p>>1;
    }
    return ans; 
}

mat dmatqp(char* n,mat a){//十进制矩阵快速幂(类比二进制写) 
    mat ans;
    int i,j;
    for(i=1;i<=N;i++)
        for(j=1;j<=N;j++)
            if(i==j)ans.m[i][j]=1;
            else ans.m[i][j]=0;
    int len=strlen(n);
    for(i=len-1;i>=0;i--){
	int num=n[i]-'0';
	for(j=1;j<=num;j++)  ans=mul(ans,a);//这里处理的是每一位的系数 
	mat tmp=a;
	for(j=1;j<=9;j++)  a=mul(a,tmp);//这里计算下一位的基数 
    }
	return ans;
}

int main(){
    ll x0,x1,a,b;
    scanf("%lld%lld%lld%lld",&x0,&x1,&a,&b);
    scanf("%s",str);
    scanf("%lld",&mod);
    int len=strlen(str);
    int l=len-1;
    while(l>=0){//这里将str数组中代表的整数减一 
	if(str[l]=='0'){
		str[l]='9';
		l--;
		continue;
	}
	else{
		str[l]--;
		break;
	}
    }
    //构造初始矩阵 
    mat mt;
    mt.m[1][1]=a;
    mt.m[1][2]=b;
    mt.m[2][1]=1;
    mt.m[2][2]=0;
    mat res=dmatqp(str,mt);
    ll answ=((res.m[1][1]*x1+mod)%mod+(res.m[1][2]*x0+mod)%mod)%mod;
    printf("%lld\n",answ%mod);
    return 0;
} 

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/98205431