您的位置:首页 > 其它

【BZOJ 2326】 [HNOI2011]数学作业

2015-03-02 08:30 330 查看

2326: [HNOI2011]数学作业

Time Limit: 10 Sec Memory Limit: 128 MB

Submit: 1100 Solved: 625

[Submit][Status]

Description





矩阵乘法。

可以用类似于秦九韶算法,把被取模的数拆开。

如123%m=(((1%m)*10+2)%m*10+3)%m

我们发现对于位数相同的数的计算方法是一样的,想到矩阵乘法。

对于1位的数:

matrix x=10^1 0 0

1 1 0

0 1 1

求1-k的值:[0 1 1]*(x^k)=[a b c] 则a就是答案

对于2位数,只要把10^1换成10^2即可,以此类推。

这个矩阵什么意思呢?

[a b c]中,a是所求,b是当前的数是几(每次都加1),c恒为1(帮助b加1的)

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define LL long long
using namespace std;
LL n,mod,a[5],l[5];
struct matrix
{
LL f[5][5];
};
matrix Mult(matrix a,matrix b)
{
matrix ans;
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
ans.f[i][j]=0LL;
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
for (int k=0;k<3;k++)
ans.f[i][j]=(ans.f[i][j]+a.f[i][k]*b.f[k][j]%mod)%mod;
return ans;
}
matrix Pow_mult(LL x,LL n)
{
matrix base,ans;
int f=0;
base.f[0][0]=x%mod,base.f[0][1]=base.f[0][2]=base.f[2][0]=base.f[1][2]=0;
base.f[1][1]=base.f[1][0]=base.f[2][1]=base.f[2][2]=1;
while (n)
{
if (n&1)
{
if (!f)
ans=base,f=1;
else ans=Mult(ans,base);
}
base=Mult(base,base);
n>>=1LL;
}
return ans;
}
int main()
{
scanf("%lld%lld",&n,&mod);
LL b=10LL,now=1LL;
a[0]=0,a[1]=1,a[2]=1;
while (1)
{
LL la=min(n,now*10LL-1LL);
matrix x=Pow_mult(b,la-now+1);
for (int i=0;i<3;i++)
{
l[i]=0LL;
for (int j=0;j<3;j++)
l[i]=(l[i]+a[j]*x.f[j][i]%mod)%mod;
}
for (int i=0;i<3;i++)
a[i]=l[i];
if (n<b) break;
b*=10LL;
now=b/10LL;
}
printf("%lld\n",a[0]);
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: