矩阵快速幂

来源:互联网 发布:战舰世界排位赛数据 编辑:程序博客网 时间:2024/06/01 10:34
情书抄写员——高级
Time Limit: 1000MS Memory Limit: 1000K   

Description

Wind的女友数量是惊人的。每个月开始时,Wind的每一个正式女友都会给他介绍k个新的女生,我们称这样的新人为“潜在的女友”(Potential GirlFriend)。通过近两个月的交往,潜在的女友总会在下一个月末成为正式的女友,并在第三个月初开始每月介绍新的女友。
我们假设,在第一个月Wind只有一个潜在的女友。Wind每个月都要给他的所有女友和潜在女友(包括本月初刚介绍来的人)写一封情书。在第a个月和第b个月,Wind有事不在,需要雇用一些“情书抄写员”来代替他完成这个操作。Wind将会让每个情书抄写员负责t封情书,并希望这个t值可以使得第a个月和第b个月的任务都能正好分尽。
Wind拜托“实习生”佳佳计算出第a个月和第b个月各需要写多少情书。为了雇用尽可能少的抄写员,Wind还想知道t的最大值是多少。
由于答案可能非常大,因此你只需要输出这三个数值mod m的结果即可。
数据规模
对于30%的数据,a; b; k ≤10;
对于80%的数据,a; b; k ≤100 000;
对于100%的数据,a; b; k ≤1 000 000 000,m ≤2的31次方- 1。
评分标准
本题设有部分分。
每个测试点共10分。
如果你的程序正确地输出了第a个月的值mod m(即第一行),则得3分;
如果你的程序正确地输出了第b个月的值mod m(即第二行),则得3分;
如果你的程序正确地输出了最大的t值mod m(即第三行),则得4分。
你需要给未输出的答案留下位置。也就是说,如果你选择不输出某个结果,你需要在结
果所在的位置留一个空行。
7

Input

输入数据一共只有一行,为四个用空格隔开的正整数,分别表示k、m、a和b,其意义如题目描述。

Output

输出数据一共有三行,每行输出一个数。
第一行为第a个月Wind需要写的情书数mod m的值;
第二行为第b个月Wind需要写的情书数mod m的值;
第三行为能同时整除第a个月的数目和第b个月的数目的最大值mod m的结果。

Sample Input

5 4 3 6

Sample Output

2
0
2

Hint

样例说明
第一个月只有一个潜在女友,第二个月该女友渐渐发展成熟,直到第三个月正式成为女
友并介绍了5个新的女生。因此,第三个月需要写6封情书,输出6 mod 4的结果,即2;
第四个月将再增加5人使得总人数达到11,到第五个月时将增加30个人。这样推下去可
以得到,第六个月需要写96封情书。数值6是能整除6和96的最大值。我们输出mod 4的结
果,即0和2。


前面是用矩阵快速幂

[好女友,即将好的女友][[1,k][1,0]]=[好女友,即将好的女友]

所以只要求出[[1,k][1,0]]的p-1次,就能算出第p月的好女友数


关键是后面的gcd(f(a),f(b))怎么算

斐波那契数列及其相似数列有这样一个性质gcd(f(a),f(b))=f(gcd(a,b))

这样就能轻松解决



#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;typedef long long ll;ll aa,bb,mm,kk;struct Matrix{    ll mat[2][2];};Matrix mul(Matrix a,Matrix b){    Matrix ret;    for(ll i=0;i<2;i++){    for(ll j=0;j<2;j++)        {            ret.mat[i][j]=0;            for(ll k=0;k<2;k++)            {                ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];    ret.mat[i][j]%=mm;            }        }    }    return ret;}Matrix pow_M(Matrix a,ll n){    Matrix ret;    memset(ret.mat,0,sizeof(ret.mat));    ret.mat[0][0]=ret.mat[1][1]=1;    Matrix temp=a;    while(n)    {        if(n&1)ret=mul(ret,temp);        temp=mul(temp,temp);        n>>=1;    }    return ret;}ll solve(ll a,ll b){ll tt=__gcd(a,b);return tt;}int main(){scanf("%lld%lld%lld%lld",&kk,&mm,&aa,&bb);Matrix dd;dd.mat[0][0]=dd.mat[1][0]=1;dd.mat[0][1]=kk;dd.mat[1][1]=0;Matrix ans1=pow_M(dd,aa-1);ll ans11=ans1.mat[0][0];//结果就是mat[0][0],不懂的话可以先理解一下矩阵ll tt1=ans11;Matrix ans2=pow_M(dd,bb-1);ll ans22=ans2.mat[0][0];ll tt2=ans22;ll t=solve(aa,bb);Matrix ans3=pow_M(dd,t-1);ll ts=ans3.mat[0][0];printf("%lld\n%lld\n%lld\n",ans11%mm,ans22%mm,ts%mm);return 0;}


0 0
原创粉丝点击