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
Sample Output
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;
}