2015年吉林省赛 Pin Pin Pin(矩阵快速幂)
2015-09-07 10:50
281 查看
题意:
我们把1~n的数连着写起来组成一个数,然后对1000000007取模f[1]=1,f[2]=12,..,f[9]=123456789...
n<=1e9,很明显我们可以得到一个递推式,f
= f[n-1]*k +n (k=10^(len(n))),由于n比较大我们需要用到矩阵来进行优化。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 3;
struct matrix {
LL m[maxn][maxn];
matrix() {
memset(m,0,sizeof(m));
}
matrix operator*(const struct matrix &A)const {
matrix C;
for(int i=0; i<maxn; i++) {
for(int j=0; j<maxn; j++) {
for(int k=0; k<maxn; k++) {
C.m[i][j]=(C.m[i][j]+A.m[i][k]*m[k][j]%mod)%mod;
}
}
}
return C;
}
friend matrix operator ^ (matrix a,int k) {
matrix ans;
for(int i = 0; i<maxn; i++)
ans.m[i][i]=1;
while(k) {
if(k&1) ans = ans*a;
k>>=1;
a=a*a;
}
return ans;
}
};
LL a[11];
matrix I;
void init() {
a[0]=1;
for(int i=1; i<11; i++) {
a[i]=a[i-1]*(LL)10;
}
for(int i=0; i<maxn; i++) {
I.m[i][i]=1;
}
}
int main() {
init();
int t,n;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
matrix ans=I;
matrix A;
A.m[0][1]=1,A.m[0][2]=1;
A.m[1][1]=1,A.m[1][2]=1;
A.m[2][2]=1;
for(int i=0; i<11&&a[i]<=n; i++) {
int num;
A.m[0][0]=a[i+1];
if(a[i+1]<=n) num = a[i+1]-a[i];
else num = n-a[i]+1;
ans=ans*(A^num);
}
printf("%lld\n",ans.m[0][2]);
}
return 0;
}
我们把1~n的数连着写起来组成一个数,然后对1000000007取模f[1]=1,f[2]=12,..,f[9]=123456789...
n<=1e9,很明显我们可以得到一个递推式,f
= f[n-1]*k +n (k=10^(len(n))),由于n比较大我们需要用到矩阵来进行优化。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 3;
struct matrix {
LL m[maxn][maxn];
matrix() {
memset(m,0,sizeof(m));
}
matrix operator*(const struct matrix &A)const {
matrix C;
for(int i=0; i<maxn; i++) {
for(int j=0; j<maxn; j++) {
for(int k=0; k<maxn; k++) {
C.m[i][j]=(C.m[i][j]+A.m[i][k]*m[k][j]%mod)%mod;
}
}
}
return C;
}
friend matrix operator ^ (matrix a,int k) {
matrix ans;
for(int i = 0; i<maxn; i++)
ans.m[i][i]=1;
while(k) {
if(k&1) ans = ans*a;
k>>=1;
a=a*a;
}
return ans;
}
};
LL a[11];
matrix I;
void init() {
a[0]=1;
for(int i=1; i<11; i++) {
a[i]=a[i-1]*(LL)10;
}
for(int i=0; i<maxn; i++) {
I.m[i][i]=1;
}
}
int main() {
init();
int t,n;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
matrix ans=I;
matrix A;
A.m[0][1]=1,A.m[0][2]=1;
A.m[1][1]=1,A.m[1][2]=1;
A.m[2][2]=1;
for(int i=0; i<11&&a[i]<=n; i++) {
int num;
A.m[0][0]=a[i+1];
if(a[i+1]<=n) num = a[i+1]-a[i];
else num = n-a[i]+1;
ans=ans*(A^num);
}
printf("%lld\n",ans.m[0][2]);
}
return 0;
}
相关文章推荐
- Linux内核监控模块-3-系统调用的截获
- test
- android moveTo、lineTo、quadTo、cubicTo、arcTo详解(转)
- 第5回 二弟呀,面子工程很重要
- iOS Wi-Fi 描述文件:关于“自动加入”和单一连接密码设置
- SOAPUI测试步骤(二)---流量控制(Conditional Goto)
- 码农们可以优越,并且应该优越
- auto layout
- android moveTo、lineTo、quadTo、cubicTo、arcTo详解(转)
- 训练样本集的制作
- 第一次启动判断
- C++的File类文件操作
- python导入模块的方法
- 移动互联网的未知魅力
- 第5回 二弟呀,面子工程很重要
- 第5回 二弟呀,面子工程很重要
- SOAPUI测试步骤(一)——断言测试(Assertion TestStep)
- ptree数据结构分析
- ZOJ - 3229 Shoot the Bullet(有源有汇上下界最大流)
- 程序在内存中的管理和组织