HDU 4291-A Short problem-循环节+矩阵快速幂
2016-08-03 18:48
381 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4291
According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
Hence they prefer problems short, too. Here is a short one:
Given n (1 <= n <= 10 18),
You should solve for
g(g(g(n))) mod 10 9 + 7
where
g(n) = 3g(n - 1) + g(n - 2)
g(1) = 1
g(0) = 0
g(n)我们可以矩阵快速幂很快求得,但是关键是g(g(n))不好求,g(n)可能很大,不能直接mod,也即g(x)!=g(x%mod),mod=1e9+7。
打表可以发现 在mod=1e9+7下,g(x)=g(x%222222224), 然后把问题转为了 求g(g(g(n))%222222224),同理再次求循环节,把问题转为求:
g(g(g(n)%183120)%222222224) ,这样就能分别三次快速幂求到答案
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 2;
long long mod;
struct Matrix
{
long long mat[2][2];
} ;
Matrix unit_matrix ;
long long n, k;
Matrix mul(Matrix a, Matrix b) //矩阵相乘
{
Matrix res;
for(int i = 0; i < k; i++)
for(int j = 0; j < k; j++)
{
res.mat[i][j] = 0;
for(int t = 0; t < k; t++)
{
res.mat[i][j] += a.mat[i][t] * b.mat[t][j];
res.mat[i][j] %= mod;
}
}
return res;
}
Matrix pow_matrix(Matrix a, long long m) //矩阵快速幂
{
Matrix res = unit_matrix;
while(m != 0)
{
if(m & 1)
res = mul(res, a);
a = mul(a, a);
m >>= 1;
}
return res;
}
Matrix get(long long n)
{
n--;
Matrix ori;
ori.mat[0][0]=1;
ori.mat[0][1]=0;
ori.mat[1][0]=0;
ori.mat[1][1]=0;
Matrix c;
c.mat[0][0]=3;
c.mat[0][1]=1;
c.mat[1][0]=1;
c.mat[1][1]=0;
Matrix ans = pow_matrix(c, n);
ans = mul(ori,ans);
return ans;
}
int main()
{
k=2;
int i, j, t;
//初始化单位矩阵 //类似快速幂的 ans=1; 如今是ans=单位矩阵
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
unit_matrix.mat[i][j] = 0;
for(i = 0; i < 2; i++)
unit_matrix.mat[i][i] = 1;
while(scanf("%lld",&n)!=EOF)
{
if (n%183120==0)
{
printf("0\n");
continue;
}
mod=183120;
Matrix ans=get(n);
mod=222222224;
if (ans.mat[0][0]==0)
{
printf("0\n");
continue;
}
ans=get(ans.mat[0][0]);
mod=(1e9)+7;
if (ans.mat[0][0]==0)
{
printf("0\n");
continue;
}
ans=get(ans.mat[0][0]);
printf("%lld\n", ans.mat[0][0]);
}
return 0;
}
According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
Hence they prefer problems short, too. Here is a short one:
Given n (1 <= n <= 10 18),
You should solve for
g(g(g(n))) mod 10 9 + 7
where
g(n) = 3g(n - 1) + g(n - 2)
g(1) = 1
g(0) = 0
g(n)我们可以矩阵快速幂很快求得,但是关键是g(g(n))不好求,g(n)可能很大,不能直接mod,也即g(x)!=g(x%mod),mod=1e9+7。
打表可以发现 在mod=1e9+7下,g(x)=g(x%222222224), 然后把问题转为了 求g(g(g(n))%222222224),同理再次求循环节,把问题转为求:
g(g(g(n)%183120)%222222224) ,这样就能分别三次快速幂求到答案
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 2;
long long mod;
struct Matrix
{
long long mat[2][2];
} ;
Matrix unit_matrix ;
long long n, k;
Matrix mul(Matrix a, Matrix b) //矩阵相乘
{
Matrix res;
for(int i = 0; i < k; i++)
for(int j = 0; j < k; j++)
{
res.mat[i][j] = 0;
for(int t = 0; t < k; t++)
{
res.mat[i][j] += a.mat[i][t] * b.mat[t][j];
res.mat[i][j] %= mod;
}
}
return res;
}
Matrix pow_matrix(Matrix a, long long m) //矩阵快速幂
{
Matrix res = unit_matrix;
while(m != 0)
{
if(m & 1)
res = mul(res, a);
a = mul(a, a);
m >>= 1;
}
return res;
}
Matrix get(long long n)
{
n--;
Matrix ori;
ori.mat[0][0]=1;
ori.mat[0][1]=0;
ori.mat[1][0]=0;
ori.mat[1][1]=0;
Matrix c;
c.mat[0][0]=3;
c.mat[0][1]=1;
c.mat[1][0]=1;
c.mat[1][1]=0;
Matrix ans = pow_matrix(c, n);
ans = mul(ori,ans);
return ans;
}
int main()
{
k=2;
int i, j, t;
//初始化单位矩阵 //类似快速幂的 ans=1; 如今是ans=单位矩阵
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
unit_matrix.mat[i][j] = 0;
for(i = 0; i < 2; i++)
unit_matrix.mat[i][i] = 1;
while(scanf("%lld",&n)!=EOF)
{
if (n%183120==0)
{
printf("0\n");
continue;
}
mod=183120;
Matrix ans=get(n);
mod=222222224;
if (ans.mat[0][0]==0)
{
printf("0\n");
continue;
}
ans=get(ans.mat[0][0]);
mod=(1e9)+7;
if (ans.mat[0][0]==0)
{
printf("0\n");
continue;
}
ans=get(ans.mat[0][0]);
printf("%lld\n", ans.mat[0][0]);
}
return 0;
}
相关文章推荐
- HDU 4291 A Short problem(矩阵快速幂+循环节)
- hdu 4291 A Short problem (矩阵快速幂+循环节)
- HDU 4291 A Short problem (2012成都网络赛,矩阵快速幂+循环节)
- HDU 4291 A Short problem(找循环节+快速幂矩阵)
- HDU 4291 A Short problem(矩阵快速幂+循环节)
- HDU 4291 A Short problem // 矩阵快速幂, 循环节
- 【矩阵快速幂 && 循环节】HDU - 4291 A Short problem
- 循环节 + 矩阵快速幂 - HDU 4291 A Short problem
- D - A Short problem HDU - 4291——矩阵快速幂
- HDU 4291 A Short problem(矩阵+循环节)
- hdu 4291 A Short problem(矩阵快速幂)
- HDU 4291 A Short problem(矩阵快速幂取模求循环节)
- HDU 4291 A Short problem(矩阵+循环节)
- hdu 4291 A Short problem(矩阵+取模循环节)
- HDU 4291:A Short problem_成都赛区网络赛—矩阵快速幂
- hdu 4291 A Short problem 打表找规律&矩阵快速幂
- HDU-4291 A Short problem(矩阵快速幂)
- 【HDU】4291 A Short problem 矩阵快速幂
- hdu 4291 A Short problem(矩阵快速幂)
- hdu 4291 A Short problem(矩阵+取模循环节)