D. Iterated Linear Function
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Consider a linear function f(x) = Ax + B. Let’s define g(0)(x) = x and g(n)(x) = f(g(n - 1)(x)) for n > 0. For the given integer values A, B, n and x find the value of g(n)(x) modulo 109 + 7.
Input
The only line contains four integers A, B, n and x (1 ≤ A, B, x ≤ 109, 1 ≤ n ≤ 1018) — the parameters from the problem statement.
Note that the given value n can be too large, so you should use 64-bit integer type to store it. In C++ you can use the long long integer type and in Java you can use long integer type.
Output
Print the only integer s — the value g(n)(x) modulo 109 + 7.
Examples
inputCopy
3 4 1 1
outputCopy
7
inputCopy
3 4 2 1
outputCopy
25
inputCopy
3 4 3 1
outputCopy
79
way 1
利用gn(x)= f(gn−1(x))=A∗gn−1(x)+B
构造一个矩阵A使得:
(gn−1(x),B)∗A=(gn(x),B)
那么矩阵A
[A 0]
[1 1]
所以
(g0(x),B)∗An=(gn(x),B)
ac代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef double db;
#define dep(i,a,b) for(int i=(a);i>=(b);i–)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define mes§ memset(p,0,sizeof§)
#define mod 1000000007
using namespace std;
struct matrix{
ll m[2][2];
}ans,res;
matrix mul(matrix x,matrix y){
matrix temp;
rep(i,0,1)
rep(j,0,1)
temp.m[i][j]=0;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
temp.m[i][j]+=((x.m[i][k]%mod)*(y.m[k][j]%mod))%mod;
return temp;
}
matrix quickpow(ll n){
ans.m[0][0]=1;ans.m[1][1]=1;ans.m[0][1]=0;ans.m[1][0]=0;
while(n){
if(n&1)
ans=mul(ans,res);
res=mul(res,res);
n=n>>1;
}
return ans;
}
int main()
{
ll a,b,n,x;matrix q;
cin>>a>>b>>n>>x;
res.m[0][0]=a;res.m[0][1]=0;res.m[1][0]=1;res.m[1][1]=1;
q=quickpow(n);
cout<<(q.m[0][0]*x+q.m[1][0]*b)%mod<<endl;
return 0;
}
way2
通过公式推导得f=((a^n)-1)/(a-1)*b+ (a的n方)*x
由于a的n次方很大,不能直接取模再除,要乘以分母的乘法逆元
费马小定理求逆元:
在m是素数的情况下,对任意整数x都有x^m ≡ x(mod m)。
如果x为整数且无法被m整除,则有x^(m−1) ≡ 1(mod m)。
所以可以在m为素数的情况下求出一个数的逆元,x * x^(m−2) ≡ 1(mod m),x^(m−2)即为逆元。
ac代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef double db;
#define dep(i,a,b) for(int i=(a);i>=(b);i–)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define mes§ memset(p,0,sizeof§)
using namespace std;
const ll mod=1e9+7;
//此法由于等比数列求和公式中有除法,直接取mod会出错,因此,用乘法逆元
ll quickpow(ll a, ll n)//计算a^n % mod
{
ll re = 1;
while(n)
{
if(n & 1)//判断n的最后一位是否为1
re = (re * a) % mod;
n >>= 1;//舍去n的最后一位
a = (a * a) % mod;//将a平方
}
return re % mod;
}
int main()
{
ll a,b,n,x;
cin>>a>>b>>n>>x;
if(a==1) cout<<(x+(b%mod)(n%mod))%mod<<endl;
else{
ll temp=quickpow(a,n),temp2=quickpow(a-1,mod-2);
ll ans=(((temp-1)temp2)%modb+tempx)%mod;
cout<<ans<<endl;
}
return 0;
}