bzoj 2326: [HNOI2011]数学作业 矩阵乘法

本文介绍了一种解决数学难题的方法,即计算Concatenate(1...N)ModM的值,通过矩阵递推的方式进行分段计算,适用于大数运算场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:给定正整数 N 和 M
要求计算 Concatenate (1 … N) Mod M 的值,其中 Concatenate (1 …N)是将所有正整数 1, 2, …, N 顺序连接起来得到的数。
例如,N = 13, Concatenate (1 … N)=12345678910111213.小C 想了大半天终于意识到这是一道不可能手算出来的题目,
于是他只好向你求助,希望你能编写一个程序帮他解决这个问题。
Input
只有一行且为用空格隔开的两个正整数N和M,
1≤N≤10181≤N≤10^{18}1N10181≤M≤1091≤M≤10^91M109.

Output
仅包含一个非负整数,表示 Concatenate (1 … N) Mod M 的值。

Sample Input
13 13
Sample Output
4

分析:
f[i]=Concatenate(1..i)f[i]=Concatenate(1..i)f[i]=Concatenate(1..i)
f[i]=f[i−1]∗10len+if[i]=f[i-1]*10^{len}+if[i]=f[i1]10len+i,其中lenlenleniii的位数。
考虑矩阵递推。首先至少有f[i−1]f[i-1]f[i1]iii这两个项,然后发现不能实现对iii的递推,还要加一个常数项。
所以,
(f[i−1]i1)∗(10len00110011)=(f[i]i+11)\begin{pmatrix} f[i-1] & i & 1 \end{pmatrix}*\begin{pmatrix}10^{len} & 0 & 0 \\ 1 & 1 & 0 \\ 0 & 1 &1 \end{pmatrix}=\begin{pmatrix} f[i] & i+1 & 1 \end{pmatrix}(f[i1]i1)10len10011001=(f[i]i+11)
因为不同位数的数矩阵不同,所以要分段计算。

代码:

/**************************************************************
    Problem: 2326
    User: ypxrain
    Language: C++
    Result: Accepted
    Time:52 ms
    Memory:1292 kb
****************************************************************/
 
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
 
using namespace std;
 
LL n,m,k,num,x,last;
 
struct matrix{
    int n,m;
    LL a[4][4];
}A,B,C;
 
matrix operator *(matrix a,matrix b)
{
    matrix c;
    c.n=a.n,c.m=b.m;
    for (int i=0;i<=c.n;i++)
    {
        for (int j=0;j<=c.m;j++) c.a[i][j]=0;
    }
    for (int k=1;k<=a.m;k++)
    {
        for (int i=1;i<=a.n;i++)
        {
            for (int j=1;j<=b.m;j++)
            {
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%m)%m;
            }
        }
    }
    return c;
}
 
void power(LL k)
{
    if (k==1)
    {
        B=A;
        return;
    }
    power(k/2);
    B=B*B;
    if (k&1) B=B*A;
}
 
int main()
{
    scanf("%lld%lld",&n,&m);    
    C.n=1,C.m=3;
    C.a[1][1]=0,C.a[1][2]=1,C.a[1][3]=1;
    num=1;
    x=last=0;
    while (x<n)
    {
        x=x*10+9;
        if (x>=n) k=n-last;
             else k=x-last;
        last=x;
        num=(num*10)%m;
        A.n=3,A.m=3;
        A.a[1][1]=num,A.a[1][2]=0,A.a[1][3]=0;
        A.a[2][1]=1,A.a[2][2]=1,A.a[2][3]=0;
        A.a[3][1]=0,A.a[3][2]=1,A.a[3][3]=1;
        power(k);
        C=C*B;
    }
    printf("%lld\n",C.a[1][1]);
}
内容概要:本文探讨了在MATLAB/SimuLink环境中进行三相STATCOM(静态同步补偿器)无功补偿的技术方法及其仿真过程。首先介绍了STATCOM作为无功功率补偿装置的工作原理,即通过调节交流电压的幅值和相位来实现对无功功率的有效管理。接着详细描述了在MATLAB/SimuLink平台下构建三相STATCOM仿真模型的具体步骤,包括创建新模型、添加电源和负载、搭建主电路、加入控制模块以及完成整个电路的连接。然后阐述了如何通过对STATCOM输出电压和电流的精确调控达到无功补偿的目的,并展示了具体的仿真结果分析方法,如读取仿真数据、提取关键参数、绘制无功功率变化曲线等。最后指出,这种技术可以显著提升电力系统的稳定性与电能质量,展望了STATCOM在未来的发展潜力。 适合人群:电气工程专业学生、从事电力系统相关工作的技术人员、希望深入了解无功补偿技术的研究人员。 使用场景及目标:适用于想要掌握MATLAB/SimuLink软件操作技能的人群,特别是那些专注于电力电子领域的从业者;旨在帮助他们学会建立复杂的电力系统仿真模型,以便更好地理解STATCOM的工作机制,进而优化实际项目中的无功补偿方案。 其他说明:文中提供的实例代码可以帮助读者直观地了解如何从零开始构建一个完整的三相STATCOM仿真环境,并通过图形化的方式展示无功补偿的效果,便于进一步的学习与研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值