zoukankan      html  css  js  c++  java
  • P3216 [HNOI2011]数学作业 (矩阵快速幂)

    P3216 [HNOI2011]数学作业

    题目描述

    小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:

    给定正整数 NN 和 MM ,要求计算 Concatenate (1 .. N) Concatenate(1..N) ModMod MM 的值,其中 Concatenate (1 .. N) Concatenate(1..N) 是将所有正整数 1, 2, …, N1,2,…,N 顺序连接起来得到的数。例如, N = 13N=13 , Concatenate (1 .. N)=12345678910111213Concatenate(1..N)=12345678910111213 .小C 想了大半天终于意识到这是一道不可能手算出来的题目,于是他只好向你求助,希望你能编写一个程序帮他解决这个问题。

    输入输出格式

    输入格式:
    从文件input.txt中读入数据,输入文件只有一行且为用空格隔开的两个正整数N和M,其中30%的数据满足 1≤N≤10000001≤N≤1000000 ;100%的数据满足 1≤N≤10^{18}1≤N≤$ 10^18 ( 且 1≤M≤) 10^9 (1≤M≤1) 0^9 $
    .
    输出格式:
    输出文件 output.txt 仅包含一个非负整数,表示 Concatenate (1 .. N)Concatenate(1..N) ModMod MM 的值。

    输入输出样例

    输入样例#1:
    13 13
    输出样例#1:
    4

    递推式容易得到:$$ f[i+1]=f[i]*10^{k}+i+1 $$
    范围 $ n<=10^{18} $
    线性算法肯定TLE,那就考虑log的算法(快速幂或者倍增)
    考虑把递推式转换成矩阵
    递推式有三项
    经验告诉我们,也许要用到(3*3)的矩阵
    经过一系列 碰数,凑数,计算
    我们得到矩阵

    [egin{pmatrix} f[n+1],n+1,1 end{pmatrix}= egin{pmatrix} f[n],n,1 end{pmatrix} imes egin{bmatrix} 10^{k},0,0\1,1,0\1,1,1 end{bmatrix} ]

    从而可以得到

    [egin{pmatrix} f[n+1],n+1,1 end{pmatrix}= =egin{pmatrix} f[1],1,1 end{pmatrix} imes egin{bmatrix} 10^{k},0,0\1,1,0\1,1,1end{bmatrix}^{n-1}]

    ps:k是位数

    k虽然是不确定的,但k的范围却很小 <=18
    所以分开做就可以了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    using namespace std;
    ll n,mod;
    struct node {
    	ll m[4][4];
    } ans,ss,a;
    node mul(node x,node y) {
    	node c= {};
    	for(int i=1; i<=3; ++i)
    		for(int j=1; j<=3; ++j)
    			for(int k=1; k<=3; ++k)
    				c.m[i][j]=(c.m[i][j]+(x.m[i][k]*y.m[k][j])%mod)%mod;
    	return c;
    }
    void fpow(ll p) {
    	while(p) {
    		if(p&1)	ans=mul(ans,ss);
    		ss=mul(ss,ss);
    		p>>=1;
    	}
    }
    int main() {
    	//全部开long long不要质疑
    	cin>>n>>mod;
    	ans.m[1][3]=a.m[1][1]=a.m[2][1]=a.m[2][2]=a.m[3][1]=a.m[3][2]=a.m[3][3]=1;
    	for(ll i=1,j; i<=n; i=j+1) {
    		j=i*10-1;
    		if(j>n) j=n;
    		a.m[1][1]=a.m[1][1]*(ll)10%mod;
    		ss=a;
    		fpow(j-i+1);
    	}
    	printf("%lld
    ",ans.m[1][1]%mod);
    	return 0;
    }
    

    自己还是太弱,最后处理菜的要死

  • 相关阅读:
    chart控件多个ChartArea
    winform chart画折线,波形图,多条数据
    C# Chart 折线图 多条数据展示
    task一个任务结束后执行另一个操作
    C#多线程同步 读写锁ReaderWriterLock的用法
    C# 多线程文件读写整理总结
    vue解决跨域问题
    接前端页面
    使用vue+zrender绘制体温单 三测单(2)
    使用vue+zrender绘制体温单 三测单(1)
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9301009.html
Copyright © 2011-2022 走看看