zoukankan      html  css  js  c++  java
  • 【洛谷P3216】【BZOJ2326】数学作业【矩阵乘法】

    题目大意:

    题目链接:
    洛谷:https://www.luogu.org/problemnew/show/P3216
    Bzoj:https://www.lydsy.com/JudgeOnline/problem.php?id=2326
    123...n % moverline{123...n} \% m


    思路:

    这种矩阵乘法的题目一看n1018nleq 10^{18}的数据范围就明显地提示了算法。。。
    思路还是很简单的。对于任意的f[i]f[i]表示123...i % moverline{123...i} \% mf[i+1]f[i+1]显然等于
    (f[i]×cnt+i+1) % m(f[i] imes cnt+i+1) \% m
    其中cntcnt表示i+1i+1的位数。
    显然,对于任意不同位数的ii,需要分开来矩乘。
    在这里插入图片描述

    注意long long×long longlong long imes long long可能会爆炸。
    时间复杂度O(log n)O(log n)


    代码:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    ll n,k,MOD,f[4],a[4][4];
    
    void mul(ll f[4],ll a[4][4])
    {
    	ll c[4]={0,0,0,0};
    	for (int i=1;i<=3;i++)
    		for (int j=1;j<=3;j++)
    			c[i]=(c[i]+f[j]*a[i][j])%MOD;
    	memcpy(f,c,sizeof(c)); 
    }
    
    void mulself(ll a[4][4])
    {
    	ll c[4][4];
    	memset(c,0,sizeof(c));
    	for (int i=1;i<=3;i++)
    		for (int j=1;j<=3;j++)
    			for (int k=1;k<=3;k++)
    				c[i][j]=(c[i][j]+a[i][k]*a[k][j])%MOD;
    	memcpy(a,c,sizeof(c)); 
    }
    
    int  main()
    {
    	scanf("%lld%lld",&n,&MOD);
    	f[1]=0,f[2]=0,f[3]=1;
    	for (ll m=1;m<=n;m*=10)
    	{
    		if (m>n/10) k=n-m+1;  //这个位数要矩乘的次数
    			else k=m*9;
    		a[1][1]=1; a[1][2]=0; a[1][3]=1;
    		a[2][1]=1; a[2][2]=m*10%MOD; a[2][3]=1;
    		a[3][1]=0; a[3][2]=0; a[3][3]=1;  //重置a数组
    		while (k)
    		{
    			if (k&1) mul(f,a);
    			mulself(a);
    			k>>=1;
    		}	
    	}
    	printf("%lld",f[2]);
    	return 0;
    }
    
  • 相关阅读:
    横向技术分析C#、C++和Java优劣
    XML数据流主动服务系统的设计与实现
    ASP.NET 状态管理
    Oracle中如何从BasicFile迁移到SecureFile
    让UpdatePanel支持上传文件
    C#和Visual Basic渐行渐远之匿名类型
    wpf 移动变换
    WPF 样式学习总结
    临江仙
    wpf 动画效果
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998249.html
Copyright © 2011-2022 走看看