2019 Niuke Summer Multi-School Training Camp(Fifth)Bジェネレーター1 [Decimal Matrix Fast Power]

タイトルの説明

4つの正の整数が与えられますx_0、x_1、a、bそして、あなたx_i = a \ cdot x_i _-_ 1 + b \ cdot x_i _-_ 2はすべてのために知っていますi \ geq 2

2つの正の整数nとMODが与えられた場合、MODをx_n法として計算してください

問題は単純に見えますか?驚き!nの値には多くの桁が含まれる場合があります。

説明を入力してください 

入力には2行が含まれます。
最初の行には4つの整数x_0、x_1、a、b1 \ leq x_0、x_1、a、b \ leq 10 ^ 9が含まれています 
2行目には、2つの整数n MOD(1 \ leq n <10 ^(^ 1 ^ 0 ^^^ 6 ^)、10 ^ 9 <MOD \ leq 2 \ times 10 ^ 9、nには先行ゼロはありません)が含まれています。

出力の説明 

答えを表す1つの整数を出力します。

 入力例1

1 1 1 1
10 1000000001

出力例1 

89

解説 

結果のシーケンスxはフィボナッチ数列です。11番目のアイテムは89です。

入力例2 

1315 521 20185 5452831
9999999999999999999999999999999999999 1000000007

出力例2 

914730061

主なアイデア:

開始項と再帰式を考えると、n番目の項MODの値が必要です。

分析:

開始項と再帰的な式があります。行列の高速指数を考えるのは簡単ですが、nは非常に大きくなります。バイナリマトリックスの高速指数を使用すると、確実にタイムアウトになり、10進数を考慮すれば10 ^ 6、複雑さは問題ありません

具体的な説明については、コードを参照してください。

#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;
} 

 

公開された30元の記事 ウォンの賞賛5 ビュー900

おすすめ

転載: blog.csdn.net/qq_42840665/article/details/98205431