hdu 4602(推公式、矩阵快速幂)
2018-01-28 19:55
399 查看
/*
hdu 4602
题目大意是
将一个数n写成多个整数相加的形式
问所有式子里面1、2、3……n有多少个
1-5的所有组合可以写成一下形式
1 2 3 4 5
1 1 2 5 12 28
2 1 2 5 12
3 1 2 5
4 1 2
5 1
我们横着看每一行可以找到规律
f(x)=2*f(x-1)+2^(x-3)(x>=3)
竖着看可以发现,和横着逆时针旋转90度是一样的
也就是说对于n==5而言
第一列与第五行是相等的,第二列与第四行是相等的
我们可以找到规律,若第i行和第j列相等
则i+j==n+1
现在题目给了第k行,则我们可以先求出是第几列
然后套用上面找到的公式
注意特判:
1.行数最大值一定与列数相等,若给定的行数k>n则不存在
2。求出来的列数是1或者2时不符合上述规律
之后矩阵快速幂即可
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#define pi acos(-1.0)
#define ll long long
#define MAX 3
#define mod 1000000007
using namespace std;
struct matrix
{
ll m[MAX][MAX];
};
matrix matrixmul(matrix a,matrix b)
{
matrix c;
for(int i=1; i<=2; i++)
for(int j=1; j<=2; j++)
{
c.m[i][j]=0;
for(int k=1; k<=2; k++)
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
c.m[i][j]%=mod;
}
return c;
}
matrix quickpow(matrix m,int n)
{
matrix b;
memset(b.m,0,sizeof(b.m));
for(int i = 1; i <= 2; i++)
b.m[i][i] = 1;
while(n>=1)
{
if(n&1)
b=matrixmul(b,m);
n=n>>1;
m=matrixmul(m,m);
}
return b;
}
int main()
{
int t;
cin>>t;
while(t--)
{
matrix m;
m.m[1][1]=2;
m.m[1][2]=1;
m.m[2][1]=0;
m.m[2][2]=2;
int n,k;
cin>>n>>k;
if(k>n)
{
cout<<0<<endl;
continue;
}
int cnt=n-k+1;
if(cnt==1)
{
cout<<1<<endl;
continue;
}
if(cnt==2)
{
cout<<2<<endl;
continue;
}
matrix res=quickpow(m,cnt-2);
ll ans=((res.m[1][1]*2)%mod+res.m[1][2])%mod;
cout<<ans<<endl;
}
return 0;
}
hdu 4602
题目大意是
将一个数n写成多个整数相加的形式
问所有式子里面1、2、3……n有多少个
1-5的所有组合可以写成一下形式
1 2 3 4 5
1 1 2 5 12 28
2 1 2 5 12
3 1 2 5
4 1 2
5 1
我们横着看每一行可以找到规律
f(x)=2*f(x-1)+2^(x-3)(x>=3)
竖着看可以发现,和横着逆时针旋转90度是一样的
也就是说对于n==5而言
第一列与第五行是相等的,第二列与第四行是相等的
我们可以找到规律,若第i行和第j列相等
则i+j==n+1
现在题目给了第k行,则我们可以先求出是第几列
然后套用上面找到的公式
注意特判:
1.行数最大值一定与列数相等,若给定的行数k>n则不存在
2。求出来的列数是1或者2时不符合上述规律
之后矩阵快速幂即可
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#define pi acos(-1.0)
#define ll long long
#define MAX 3
#define mod 1000000007
using namespace std;
struct matrix
{
ll m[MAX][MAX];
};
matrix matrixmul(matrix a,matrix b)
{
matrix c;
for(int i=1; i<=2; i++)
for(int j=1; j<=2; j++)
{
c.m[i][j]=0;
for(int k=1; k<=2; k++)
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
c.m[i][j]%=mod;
}
return c;
}
matrix quickpow(matrix m,int n)
{
matrix b;
memset(b.m,0,sizeof(b.m));
for(int i = 1; i <= 2; i++)
b.m[i][i] = 1;
while(n>=1)
{
if(n&1)
b=matrixmul(b,m);
n=n>>1;
m=matrixmul(m,m);
}
return b;
}
int main()
{
int t;
cin>>t;
while(t--)
{
matrix m;
m.m[1][1]=2;
m.m[1][2]=1;
m.m[2][1]=0;
m.m[2][2]=2;
int n,k;
cin>>n>>k;
if(k>n)
{
cout<<0<<endl;
continue;
}
int cnt=n-k+1;
if(cnt==1)
{
cout<<1<<endl;
continue;
}
if(cnt==2)
{
cout<<2<<endl;
continue;
}
matrix res=quickpow(m,cnt-2);
ll ans=((res.m[1][1]*2)%mod+res.m[1][2])%mod;
cout<<ans<<endl;
}
return 0;
}
相关文章推荐
- HDU 6198 推公式+矩阵快速幂
- HDU 6050 Funny Function(矩阵快速幂或公式)
- hdu 4565 公式推导+矩阵快速幂
- hdu 4602 递推关系矩阵快速幂模
- (矩阵快速幂, 数学公式推导)HDU 6050 Funny Function
- HDU 3117 Fibonacci Numbers(矩阵快速幂+公式)
- HDU - 6050(推公式、矩阵快速幂)
- hdu-4602-Partition(矩阵快速幂)
- ZOJ 3690 & HDU 3658 (矩阵快速幂+公式递推)
- HDU 2256 & HDU 4565 (矩阵快速幂 + 公式推演)
- HDU - 5950 Recursive sequence 矩阵快速幂(由公式推矩阵快速幂简单讲解)
- hdu 3411 推公式+矩阵快速幂
- hdu 3117 Fibonacci Numbers 矩阵快速幂+公式
- hdu 4565(推公式、矩阵快速幂)
- hdu 4602 Partition(矩阵快速幂乘法)
- HDU 4602 Partition (矩阵快速幂或求通项)
- HDU_2604 矩阵快速幂 较难推的公式
- 【公式+矩阵快速幂】HDU_3117 Fibonacci Numbers
- HDU-4686 Arc of Dream(推公式+矩阵快速幂)
- hdu 2256 Problem of Precision(矩阵快速幂 推公式)