P3216-[HNOI2011]数学作业【矩阵乘法,数学】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/89256543

正题

题目链接:https://www.luogu.org/problemnew/show/P3216


题目大意

1 n 1\sim n 连起来 % m \% m 之后的值。


解题思路

我们可以考虑矩乘,但是当 x x 位数时每次乘上 1 0 x 10^x ,所以我们对于不同位分开处理就好了。


c o d e code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int Size=4;
struct matrix{
	ll a[Size][Size];
}f,a;
ll n,m,k,pn,z;
matrix operator *(matrix &a, matrix &b) {
    matrix c;
    memset(c.a,0,sizeof(c.a));
    for (ll i=0;i<Size;i++)
        for (ll j=0;j<Size;j++)
            for (ll k=0;k<Size;k++)
                (c.a[i][j]+=a.a[i][k]*b.a[k][j]%m)%=m;
    return c;
}
ll pows(ll x,ll b)
{
	ll ans=1;
	while(b){
		if(b&1) ans=ans*x%m;
		x=x*x%m;b>>=1;
	}
	return ans;
}
void make_matrix(ll k)
{
	memset(a.a,0,sizeof(a.a));
	a.a[0][0]=z*10%m;
	a.a[1][0]=1;a.a[2][1]=1;
	a.a[1][1]=1;a.a[2][2]=1;
	f.a[0][1]=z%m;
	f.a[0][2]=1; 
}
void power(ll b)
{
	/*while(b--)
	  f=f*a;*/
	while(b){
		if(b&1) f=f*a;
		a=a*a;b>>=1;
	}
}
int main()
{
	scanf("%lld%lld",&n,&m);
	pn=n;
	k=0;z=1;
	while(n)
	{
		k++;
		make_matrix(k);
		if(n/10)
			power(z*10-z);
		else
			power(pn-z+1);
		n/=10;z*=10;
	}
	printf("%lld",f.a[0][0]);
} 

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/89256543