最新文章

フロム/TRUE 日中罗马音歌词

フロム/TRUE 日中罗马音歌词

フロム 作词:唐沢美帆 作曲:南田健吾 / h-wonder 歌:TRUE(唐沢美帆) 下 

DEAREST DROP/田所あずさ 日中罗马音歌词

DEAREST DROP/田所あずさ 日中罗马音歌词

DEAREST DROP 作词:Q-MHz / 藤本記子 / 結城アイラ 作曲:Q-MHz 

いつもこの場所で/彩音 日中罗马音歌词

いつもこの場所で/彩音 日中罗马音歌词

いつもこの場所で

作词:志倉千代丸、江幡育子
作曲:志倉千代丸、磯江俊道
歌:彩音

下载Word格式文档(.docx)

歌词来源:いつもこの場所で(剧场版《命运石之门 负荷领域的既视感》主题曲 / 劇場版「STEINS) – 彩音 – 单曲 – 网易云音乐
翻译来源:いつもこの場所で(剧场版《命运石之门 负荷领域的既视感》主题曲 / 劇場版「STEINS) – 彩音 – 单曲 – 网易云音乐
翻译作者:谎言-葬仪-死去 – 用户 – 网易云音乐
信息来源:いつもこの場所で | Bangumi 番组计划
罗马音来源:自制 航空母艦飛龍 – 用户 – 网易云音乐
协力:Google 翻译

いつか僕らが 未来 振り返る時には
Itsuka bokura ga mirai furikaeru tokiniwa
何时我们回顾未来的时候
いつもこの場所で キミが笑って
Itsumo kono basho de kimi ga waratte
你总在此处微笑

残酷に過ぎ行く 時の中で
Zankoku ni sugiyuku toki no naka de
探求的事物
探し求めていたもの
Sagashi motomete ita mono
随着时间残酷地流逝
すれ違う世界に 閉じ込められた
Surechigau sekai ni toji komerareta
微弱的光芒
目に見えぬヒカリ
Me ni mienu Hikari
被关在擦身而过的世界里

特別なほど 愛する者へ
Tokubetsuna hodo aisuru mono e
隐瞒着
打ち明けられずにいた
Uchiake rarezu ni ita
特别而心爱的人
過ごした日々の 一つ一つが
Sugoshita hibi no hitotsu hitotsu ga
解开过去日子中
戸惑いをピリオドに変える
Tomadoi o piriodo ni kaeru
一个个的困惑

いつか僕らが 未来 振り返る時には
Itsuka bokura ga mirai furikaeru tokiniwa
何时我们回顾未来的时候
いつもこの場所で キミが笑って
Itsumo kono basho de kimi ga waratte
你总在此处微笑
重ね合った みんなの想いが
Kasaneatta min’na no omoi ga
大家的思念交织重叠
世界線を創る
Sekai-sen o tsukuru
将世界线创造
どんな雨にも 負けぬ
Don’na ame ni mo makenu
无论怎样的风雨 我们都不认输
信じ合える気持ち
Shinjiaeru kimochi
互相信任的心情
この空の観測者
Kono sora no kansoku-sha
这片天空的观测者
この空は明日の証明
Kono sora wa asu no shōmei
这片天空是明天的证明

いつまでも変わらぬ
Itsu made mo kawaranu
永远不会改变的景色
景色なんて 絶対に叶わぬ夢
Keshiki nante zettai ni kanawanu yume
绝对无法实现的梦想
奇跡のような出会い
Kiseki no yōna deai
奇迹般的邂逅
せめてあの日を 消したりしないで
Semete ano hi o keshi tari shinaide
至少想要留住那一天

好きな気持ちが 勇気に変わる
Sukina kimochi ga yūki ni kawaru
喜欢你的心情化成了勇气
科学的じゃないけど
Kagaku-teki janaikedo
虽然这不科学
戸惑いのない キミの言葉が
Tomadoi no nai kimi no kotoba ga
不要不知所措
本当の答えを導く
Hontō no kotae o michibiku
你的话语指引着真正的答案

あの日僕らは 出会い 大切な何かを
Anohi bokurawa deai taisetsuna nanika o
那一天 我们有什么重要的东西相遇了
いつもこの場所で 探していたね
Itsumo kono basho de sagashite ita ne
曾经总是在此处寻找
何気なく 過ぎゆく時間の
Nanigenaku sugi yuku jikan no
无意间 在流逝的时间中
その意味を知ってる
Sono imi o shitteru
明白了这其中的意义
たとえどんなに 二人 離れてしまっても
Tatoe don’nani futari hanarete shimatte mo
即使两人分隔两地
この空の観測者 この空は明日の証明
Kono sora no kansoku-sha kono sora wa asu no shōmei
这片天空的观测者,这片天空是明天的证明

たとえ僕らは 遠く 離れてしまっても
Tatoe bokura wa tōku hanarete shimatte mo
无论我们分隔多远
いつもこの場所で 繋がっている
Itsumo kono basho de tsunagatte iru
总是在此处相连
切なくてロマンチックだね
Setsunakute romanchikkuda ne
悲伤而又浪漫
まだ知らない明日
Mada shiranai ashita
未知的明天

いつか僕らが 未来 振り返る時には
Itsuka bokura ga mirai furikaeru tokiniwa
何时我们回顾未来的时候
いつもこの場所で キミが笑って
Itsumo kono basho de kimi ga waratte
你总在此处微笑
重ね合った みんなの想いが 世界線を創る
Kasaneatta min’na no omoi ga sekai-sen o tsukuru
大家的思念交织重叠,将世界线创造
どんな雨にも 負けぬ 信じ合える気持ち
Don’na ame ni mo makenu shinjiaeru kimochi
无论怎样的风雨 我们都不认输 互相信任的心情
この空の観測者 この空は明日の証明
Kono sora no kansoku-sha kono sora wa asu no shōmei
这片天空的观测者,这片天空是明天的证明

NOIP2017游记

NOIP2017游记

谨以此文献给自己从初学到NOIP的一年。 11月10日 早上一早起来,打开洛谷,日常签到。 

密码保护:浴谷八连测总结

密码保护:浴谷八连测总结

无法提供摘要。这是一篇受保护的文章。

[NOIP1999]旅行家的预算 题解

[NOIP1999]旅行家的预算 题解

旅行家的预算 NOIP1999 (洛谷P1016) 题解

题目描述

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,…,N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

输入输出格式

输入格式:

第一行,D1,C,D2,P,N。

接下来有N行。

第i+1行,两个数字,油站i离出发点的距离Di和每升汽油价格Pi。

输出格式:

所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

输入输出样例

输入样例#1:

275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2

输出样例#1:

26.95

说明

N≤6,其余数字≤500

解题思路

这题我采取的方法是模拟车在加油站之间行驶的过程,使过程中需要用的每一份油都使用能够使用的最便宜的油。这种想法比较抽象,难以理解,不过清晰并且实现起来容易。题解中会有分析和举例帮助理解。

首先说一下怎么做到“使过程中需要用的每一份油都使用能够使用的最便宜的油”。我们不断地维护可用的“燃油提供者”(即加油站)的列表。等到要用油的时候,再从列表中选取最便宜的油拿来用,而不是在到那个油站的时候就决定好加多少油。我们设想现在正打算从加油站G1行驶到G2,模拟选取最优的过程。这个过程需要讨论,细节如下:

  • 从当前可用的“提供者”中选取最便宜的备用
  • 计算从G1行驶到G2所需的油量,并且从“提供者”处买来燃油,加进车的油箱里
  • 将车从G1开到G2,再以G2为起点计算下一步的行动

可以容易得出以下的结论:

  1. 每个加油站最多能给你加一油箱的油,如果加的更多油箱装不下
  2. 只有到现在所在位置的距离小于一油箱油能够行驶的距离,在这样的加油站才能买油(实际情况是如果超出这一距离,等你到这个位置之前一油箱的油就被用完了,这些油包括了你在那个很远的油站买的油)

需要讨论的内容:

  • 如果最便宜油站到现在所在位置的距离在一油箱油能够行驶的距离之内,且这个油站还可以买够从G1到G2所需的油,那很好,直接把这些油买下来
  • 如果最便宜油站到现在所在位置的距离在一油箱油能够行驶的距离之外,或这个油站不能继续买油了,把它从列表中删去
  • 如果最便宜油站到现在所在位置的距离在一油箱油能够行驶的距离之内,且这个油站买不够从G1到G2所需的油,选择次便宜的买够,若仍不够,循环操作

以题目样例为例:




实现上,列表用堆/优先队列维护,可以将起点、终点作为油站加入列表,走到终点结束前进即可。实现代码中有详细注释。

实现代码

#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

struct gas {
    double pos, price, vol;
} g[505];

bool cmp(gas a, gas b) {
    return a.pos < b.pos;
} 

struct cmp1 {
    bool operator()(int a, int b) {
        return g[a].price > g[b].price;
    }
};

priority_queue<int, vector<int>, cmp1> pq; // 堆存可以用的油 

int n; // 注意n可以为0 
double dis, vol, doil, sprice, maxdis;

int main() {
    scanf("%lf%lf%lf%lf%d", &dis, &vol, &doil, &sprice, &n);
    maxdis = vol * doil;
    if(n == 0) { // 对n为0的特判 
        if(dis > maxdis) {
            printf("No Solution");
        } else {
            printf("%.2lf", dis / doil * sprice);
        }
        return 0;
    }
    // 把起点和终点都加入加油站的列表 
    g[0].pos = 0, g[0].price = sprice, g[0].vol = 0;
    g[n + 1].pos = dis, g[n + 1].price = -1, g[n + 1].vol = -1;
    for(int i = 1; i <= n; i++) {
        scanf("%lf%lf", &g[i].pos, &g[i].price);
        g[i].vol = 0;
    }
    sort(g, g + n + 1, cmp); 
    pq.push(0);
    int ngas = 0; // 表示现在开到了下表为ngas的加油站 
    double ncost = 0; // 表示现在的累计花费油钱 
    while(ngas < n + 1) {
        //printf("maxdis %lf dis %lf\n", maxdis, g[ngas].pos - g[pq.top()].pos);
        // 如果走的太远远处的油站就无法加油了,或是这个油站已经买了一箱油没办法再加了,这两种情况要把油站出堆 
        while(g[ngas].pos - g[pq.top()].pos > maxdis || g[pq.top()].vol >= vol) {
            pq.pop(); 
        } 
        // 无解的情况:存在相邻油站距离大于一箱油可以支持的距离 
        if(g[ngas + 1].pos - g[ngas].pos > maxdis) {
            printf("No Solution");
            return 0;
        }
        int gmin = pq.top();
        pq.pop();
        //printf("ngas %d ncost %lf gmin pos %lf price %lf vol %lf\n", ngas, ncost, g[gmin].pos, g[gmin].price, g[gmin].vol);
        double gcost = (g[ngas + 1].pos - g[ngas].pos) / doil;
        // 往前走一个油站,计算这段路程的油费开支 
        if(vol - g[gmin].vol >= gcost) { // 如果最便宜的油能够支持这一段路程 
            ncost += gcost * g[gmin].price;
            g[gmin].vol += gcost;
        } else { // 如果最便宜的油不能支持这一段路程,那么就要补充次便宜的 
            while(gcost > 1e-10) { // EPS设为1e-10避免浮点陷阱 
                double navailable = vol - g[gmin].vol; // 现在选择的油站可以买的油量 
                ncost += min(gcost, navailable) * g[gmin].price;
                gcost = max(1e-10, gcost - navailable);
                g[gmin].vol = min(vol, g[gmin].vol + gcost); 
                while(g[ngas].pos - g[pq.top()].pos > maxdis || g[pq.top()].vol >= vol) {
                    pq.pop(); 
                }
                gmin = pq.top();
            }
        }
        ngas++;
        pq.push(gmin); // 把还能加的油加进去 
        pq.push(ngas);
    }
    printf("%.2lf", ncost);
    return 0;
}
致郧中2017级:对于竞赛,请不要太悲观

致郧中2017级:对于竞赛,请不要太悲观

这是来自一个高二学长的真心话,听说下一届可能不会有竞赛培训,其实我有少许失落。毕竟经过了亲 

归并排序和逆序对问题

归并排序和逆序对问题

归并排序 归并排序是O(nlogn)排序算法(归并、快排、堆排)中最有分治特点的一个。它的 

高精度整数的运算

高精度整数的运算

本文中代码已通过洛谷P1601P2142P1303P1480P2005(封装导致TLE)、P1932(不压位数组长度不够)。

10进制高精度整数

存储

由于高精度运算的原理就是模拟手算竖式的过程,因此我们采用倒序存储应该会较为方便。等到我们需要输出时再将它正序输出即可。

以下代码如有出现

bint a = *this;

请使用自己喜欢的方法替代它,这是不建议使用的方法。(只是我懒得改233)

struct bint { // 封装 
    int num[1005], len;
    bool neg;
    
    bint(string s) {
        neg = false;
        int cnt = 0;
        for(string::reverse_iterator it = s.rbegin(); it != s.rend(); it++) { // 倒序存储 
            num[cnt] = (*it) - '0';
            cnt++;
        }
        if(cnt == 0) {
            num[0] = 0;
            cnt++;
        }
        for(int i = cnt - 1; i >= 1; i--) { // 处理前导0 
            if(num[i] == 0) cnt--;
            else break;
        } 
        len = cnt;
    }

    void print() {
        if(neg && *this != bint("0")) printf("-");
        for(int i = len - 1; i >= 0; i--) {
            printf("%d", num[i]);
        }
    }
};

比较

按位比较,没什么好说的。

 /* 关系运算符 按需实现 注意:并不带符号比较(仅比较绝对值) */ 
    bool operator > (const bint &b) {
        bint a = *this;
        if(a.len > b.len) return true;
        if(a.len < b.len) return false;
        for(int i = a.len - 1; i >= 0; i--) { 
            if(a.num[i] > b.num[i]) return true;
            if(a.num[i] < b.num[i]) return false;
        }
        return false;
    }
    
    bool operator < (const bint &b) { 
        bint a = *this; 
        if(a.len > b.len) return false;
        if(a.len < b.len) return true;
        for(int i = a.len - 1; i >= 0; i--) { 
            if(a.num[i] > b.num[i]) return false;
            if(a.num[i] < b.num[i]) return true;
        }
        return false;
    }
    
    bool operator == (const bint &b) {
        bint a = *this;
        if(a.len != b.len) return false;
        for(int i = 0; i < a.len; i++) { 
            if(a.num[i] != b.num[i]) return false; 
        } 
        return true; 
    } 

    bool operator != (const bint &b) { 
        bint a = *this; 
        return !(a == b); 
    } 

    bool operator >= (const bint &b) {
        bint a = *this;
        if(a.len > b.len) return true;
        if(a.len < b.len) return false;
        for(int i = a.len - 1; i >= 0; i--) { 
            if(a.num[i] > b.num[i]) return true;
            if(a.num[i] < b.num[i]) return false;
        }
        return true;
    }   
    
    bool operator <= (const bint &b) { 
        bint a = *this; 
        if(a.len > b.len) return false;
        if(a.len < b.len) return true;
        for(int i = a.len - 1; i >= 0; i--) { 
            if(a.num[i] > b.num[i]) return false;
            if(a.num[i] < b.num[i]) return true;
        }
        return true;
    }

加减法

高精度加法的原理基本是模拟手算的过程,即按位相加,超10进位。为了减少按位相加的次数,我们让较长的数加上较短的数,这样计算时循环的次数便是较短数的位数。每次按位相加记录进位并%=10,就可以实现进位。

至于高精度减法,同样也是模拟竖式计算。按位相减,退位记下来标记在下一位上。细节方面需要注意的是如果有前导0要记得删去,标记退位后要把该位补成正数。

这里的代码实现有功能限制,比如只接受操作数为正整数,但是减法可以得到一个负数。

    bint operator + (bint &b) {
        bint a = *this;
        if(a < b) swap(a, b);
        for(int i = 0; i < b.len; i++) { 
            a.num[i] += b.num[i]; 
        }
        int nxt = 0;
        for(int i = 0; i < a.len; i++) { // 处理进位 
            a.num[i] += nxt; nxt = a.num[i] / 10; 
            a.num[i] %= 10; 
        } if(nxt > 0) {
            a.num[a.len] = nxt;
            a.len++;
        }
        return a;
    }
    
   bint operator - (bint &b) {
    bint a = *this;
    if(a < b) {
        swap(a, b);
        a.neg = true;
    }
        for(int i = 0; i < b.len; i++) {
            a.num[i] -= b.num[i];
        }
        int nxt = 0;
        for(int i = 0; i < a.len; i++) { // 处理进位 
            a.num[i] += nxt;
            nxt = 0;
            if(a.num[i] < 0) { 
                nxt = -1; 
                a.num[i] += 10; 
            } 
        } 
        for(int i = a.len - 1; i >= 1; i--) { // 处理前导0 
            if(a.num[i] == 0) a.len--;
            else break;
        } 
        return a;
    }

乘法

乘法的原理依然是列竖式计算,这里我们用一例124*128讲解。

       1  2  4
   ×   1  2  8
--------------
       9  9  2
    2  4  8
 1  2  4
--------------
 1  5  8  7  2

在我们的手算列竖式的过程中,我们通常用乘数乘以被乘数的每一位,并顺便完成进位和求和的工作。在计算机中,每一步都要进位是一件很低效的事情,我们看看如果不自动进位会发生什么。

       1  2  4
   ×   1  2  8
--------------
       8 16 32
    2  4  8
 1  2  4
--------------
 1  5  8  7  2

可以发现,除了第一行8 16 32没有进位以外,其他并无差别。也就是说我们可以先把这个答案的每一位计算出来再处理进位。

进位的事情考虑完了,现在让我们考虑怎么得到答案每一位对应的数。在竖式中我们利用了对齐直接上下相加就可以得到,让我们给乘数和被乘数加个编号观察会发生什么。

       1  2  4
      (2)(1)(0)   i
   ×   1  2  8
      (2)(1)(0)   j
--------------
       8 16 32
    2  4  8
 1  2  4
--------------
(4)(3)(2)(1)(0)   k

由于我们倒序存储高精度数,自然要倒序运算。我们可以观察到答案的第k位可以由所有的i+j=k中乘数的第i位和被乘数的第j位数字的乘积的和得到,即以下式子。

c\left[ k\right] =\sum _{i+j=k}^{i,j}a\left[ i\right] \cdot b\left[ j\right]

我们很快能算出答案的各位数。至于处理进位直接看加法的处理方法就好。

 bint operator * (bint &b) {
        bint a = *this;
        if(a == bint("0") || b == bint("0")) return bint("0");
        bint c = bint("0");
        memset(c.num, 0, sizeof c.num);
        for(int i = 0; i < a.len; i++) {
            for(int j = 0; j < b.len; j++) {
                c.num[i + j] += a.num[i] * b.num[j]; 
            }
        } 
        c.len = a.len + b.len - 1;
        int nxt = 0;
        for(int i = 0; i < c.len; i++) { // 处理进位 
            c.num[i] += nxt; 
            nxt = c.num[i] / 10; 
            c.num[i] %= 10; 
        } 
        if(nxt > 0) c.num[c.len++] = nxt;
        return c;
    }

除法与取模

高精度数模低精度数

让我们回想一下我们在列竖式计算除法的时候是如何计算出最终余数的。以130987/21为例。

      6237
   -------
21 )130987
    126
    ------
      49        ←
      42
    ------
       78       ←
       63
    ------
       157      ←
       147
    ------
        10      ←

此例中,每一个被标注了←符号的步骤中,完成的是同一件事:取某几位对除数取模,将得到的结果扩大10倍并补上下一位继续计算(语文不太好……如果听不懂看代码吧qwq)。这便是我们模拟取模的方法。其实如果要证明也很容易,由取模的分配律(a + b) mod c = (a mod c + b mod c) mod c易得(其实我也不知道怎么得来的)。下面上代码。

    int operator % (int b) {
        int c = 0;
        bint a = *this;
        for(int i = a.len - 1; i >= 0; i--) {
            c *= 10;
            c = (c + a.num[i]) % b; 
        }
        return c;
    }

高精度数除以低精度数

从上面取模的过程中来看,我们只需要在取模的同时记录商就可以达到除法的效果。

 bint operator / (int b) {
        int c = 0;
        bint a = *this;
        for(int i = a.len - 1; i >= 0; i--) {
            c *= 10;
            c += a.num[i];
            a.num[i] = c / b;
            c %= b;
        }
        for(int i = a.len - 1; i >= 1; i--) { // 处理前导0 
            if(a.num[i] == 0) a.len--;
            else break;
        } 
        return a;
    }

高精度数除以高精度数

让我们回想我们在作竖式除法时候的步骤。仍以130987/21为例。

      6237
   -------
21 )130987
    126       ←
    ------
      49        
      42      ←
    ------
       78       
       63     ←
    ------
       157      
       147    ←
    ------
        10

这次打←符号的位置不同了。这是因为我们在每一个打←符号的步骤上都做了这么一件事情。一是选择被除数的几位补成一个恰好大于除数的数字,然后再找除数的几倍恰好小于这个数。这个倍数就成为了商其中的一位。由于我们并不想要把商算到小数点后面,自然会抛弃最后的余数,即对商向下取整。接下来要做的就是模拟刚刚的操作。

就实现上而言,我们可以把找倍数这样一个操作简化为“能减几个该数”这样的问题,并用while循环处理它即可。大家可以发现,商的位数不会大于被除数的长度减除数的长度,因此可以以这个量作为大循环的循环次数。下面是代码

 bint operator / (bint b) {
        bint a = *this;
        if(a < b) return bint("0");
        if(a == b) return bint("1");
        bint c = b;
        for(int i = 0; i < a.len - b.len; i++) { 
            c = c * bint("10"); 
        } char ans[MAXN]; 
        int now = 0; 
        int cnt = 0; 
        for(int i = a.len - b.len; i >= 0; i--) {
            while(a >= c) {
                now++;
                a = a - c;
            }
            ans[cnt] = now + '0';
            cnt++;
            now = 0;
            c = c / 10; 
        } 
        return bint(string(ans)); 
    }

高精度数模高精度数

此处我们仍可以借鉴上面的除法。可以发现其实减到最后小于除数的a就是整个除法做完之后得到的余数,那么我们把除法中一些不必要的步骤删去后模拟该过程并返回a就能得到余数。

 bint operator % (bint b) {
        if(b == bint("1")) return bint("0");
        bint a = *this;
        if(a < b) return a;
        if(a == b) return bint("0");
        bint c = b;
        for(int i = 0; i < a.len - b.len; i++) { 
            c = c * bint("10"); 
        } 
        for(int i = a.len - b.len; i >= 0; i--) {
            while(a >= c) {
                a = a - c;
            }
            c = c / 10; 
        } 
        return a; 
    }

需要注意的是,这里有一些特判,a<b时a%b=a和a%1=0都是需要注意的地方。

参考资料

  1. C语言中的高精度乘法 - longj's coding workbench - CSDN博客
  2. C语言 高精度减法 - Silence的程序实验室 - CSDN博客
  3. 【图文】高精度取模_百度文库
  4. 高精度取模 - 咸鱼 - CSDN博客
  5. C++的运算符重载 - 很不错的 blog - CSDN博客
  6. 算法总结——大整数除法 - LJWLgl的博客 - CSDN博客
  7. 题解 P1932 - 百科 - 洛谷
  8. 题解 P2005 - 百科 - 洛谷

注意

本文中所有示例代码都使用struct简单封装,但是实际遇到问题并不需要如此封装,因此你可以将其写的稍微裸一些来减少封装可能带来的额外时空开销。

高精度数压位运算

高精度的压位即是指上面int数组中一个位置存储不止1位的数字,相当于把一个10进制数转换成10n进制数进行存储和运算。压位后的高精度在进位上有些许不同,但是运算过程基本相同。

之后的重点并不会放在高精度上,因此这一章的更新也许会延后,实在抱歉。

高精度运算的其他应用

高精度运算尤其是运算后的进位是可以规定当前数的进制的。下面是一些高精度解决多进制运算问题的例题。

洛谷P1581、P1604

之后的重点并不会放在高精度上,因此这里可能不会有内容,实在抱歉。

模运算性质、快速幂(取模)

模运算性质、快速幂(取模)

模运算的一些性质 同余公式 形如a≡b (mod d)的式子被称为同余公式,因为此式中a与