如果a 与d 是整数,d 非零,那么r 满足这样的关系:
a = q*d + r , q 为整数,且0 ≤ |r| < |d|。
其中,q 被称为商,r 被称为余数。
从定义的角度来看,我们此时需要解决3种情况:
1.a、d均为负数
2.仅a为负数
3.仅b为负数
我们先引入结论:
1.对于任何同号的两个整数,其取余结果没有争议,所有语言的运算原则都是使商尽可能小。
2.对于异号的两个整数,C++/Java语言的原则是使商尽可能大,很多新型语言和网页计算器的原则是使商尽可能小。
对于C++/Java语言,我们可以更加简便的记忆为:
a = q*d + r ,余数 r 的符号与 a 的符号相同
例子:
以C++/Java语言为背景
(-7)%(-3)=-1
(-7)%(3)=-1
(7)%(-3)=1
给定一个正整数m和两个整数a和b,如果((a-b) mod m)=0,
则称a和b模m同余,记为 a≡b(mod m)。
存在关系:a=b+k*m
给定一个正整数m作为模,整数对其取模的结果有m种情况:0到m-1
此时余数不考虑负数,从数学角度来理解
我们把对m取模结果相同的整数构成的集合称为模m的一个同余类(剩余类)
同余关系是一种等价关系。
1.自反性:一个数永远和自己本身同余
2.对称性:a和b同余,b和a也就同余
3.传递性:a和b同余,b和c也同余,可以推出a和c也是同余的
完全剩余系:
从模m的每个剩余系中各取一个数得到m的数,叫做模m的一个完全剩余系
比如模5的完全剩余系:
0 , 1 , 2 , 3 , 4
0 , 6 , 2 , 8 , 19
… …
简化剩余系:
简化剩余系也称既约剩余系或缩系,是m的完全剩余系中与m互素的数构成的子集,如果模m的一个剩余类里所有数都与m互素,就把它叫做与模m互素的剩余类。
互素:两个数仅有1作为公共的因子
比如
模5的一个简化剩余系是1,2,3,4
模10的一个简化剩余系是1,3,7,9
模18的一个简化剩余系是1,5,7,11,13,17
若a、b属于模m的简化剩余系,那么a*b同样属于模m的简化剩余系。
证明:根据之前的唯一分解定理,可以得知a与m不存在相同的质因子,同样b与m也不存在,
那么ab的结果与m仍然不会存在相同的质因子,也就是与m互素,那么ab也就属于m的一个简化剩余系。
总而言之,大部分情况下,我们整体取模和分布取模的结果是一致的。
公式证明
1.消去律简单证明
ac≡bc (mod p) → a≡b (mod p g c d ( c , p ) \frac{p}{gcd(c,p)} gcd(c,p)p )
ac≡bc (mod p) 可以得到c(a-b)=kp;
此时令gcd(c,p)=d;
将两边同时除以d,可得:
c d \frac{c}{d} dc(a-b)=k p d \frac{p}{d} dp,其中 c d \frac{c}{d} dc与 p d \frac{p}{d} dp为互质关系,不存在相同因子,那么要满足等式的成立,要么k为0,存在a=b,要么是由k提供了 c d \frac{c}{d} dc,也就意味着 c d \frac{c}{d} dc是k的因子。
那么式子就可以继续改写为 c d \frac{c}{d} dc(a-b) =( c d \frac{c}{d} dck‘ ) p d \frac{p}{d} dp = c d \frac{c}{d} dc(k‘ p d \frac{p}{d} dp)
两边约去 c d \frac{c}{d} dc可得:a - b = k’ p d \frac{p}{d} dp;
也就是 a≡b (mod p g c d ( c , p ) \frac{p}{gcd(c,p)} gcd(c,p)p )
证毕。
2.a≡b(% cd) → a≡b(% d)
证明:
a= m * cd+r等于(mc)* d+r
b= n * cd+r等于(nc)* d+r
3.(a≡b(% d), a≡b(% c)) → a≡b(% LCM(c,d))
证明:
由上式,可得关系:(a - b)既可以被d 所整除,又可以被c整除。
对(a -b)、c、d进行唯一分解,以其中的某一项质因数p为例,
(a - b)于该项的指数一定大于等于c 于该项的指数,否则无法满足整除条件。
同理适用于(a - b)跟 d 的讨论;
而且这一规律适用于每个质因数。
在GCD与LCM我们知道了LCM(c,d)中,每一位质因数的指数其实是c、d在这一指数上取的最大值。
若c = 12 = (2 ^ 2)* (3 ^ 1) * (5 ^ 0)
d = 15 = (2 ^ 0) * (3 ^ 1) * ( 5 ^ 1)
那么LCM(c,d)= (2 ^ 2)* (3 ^ 1) * (5 ^ 1) = 60
而(a -b)每一项质因数的指数都大于等于c,跟d,也就大于等于其中的最大值,即LCM(c,d)在该处的指数,所以 (a - b)可以被LCM(c,d)整除,a≡b(% LCM(c,d))也就成立了。
4.若a≡b (% p),则对于任意的c,都有
(a + c) ≡ (b + c) (%p)
证明:
c= k * p+R
a= m * p+r
b= n * p+r
a+c=(k+m)* p+R+r
b+c=(k+n)* p+R+r
可知其相等
5.若a≡b (% p),则对于任意的c,都有
(a * c) ≡ (b * c) (%p)
证明:
c= k * p+R
a= m * p+r
b= n * p+r
ac=(kmd+kr+mR) * p + Rr
bc=(knd+kr+nR) * p+ Rr*
6.若a≡b (% p),则对于任意的c,都有 ( a c a^c ac) ≡ ( b c b^c bc) (%p)
证明:参考上方带模运算,进行分部取模,可以发现最后殊途同归,都是对r的c次方取模
7.若a≡b (% p),c≡d (% p),
则(a +c) ≡ (b +d) (%p)
(a - c) ≡ (b - d) (%p)
(a * c) ≡ (b * d) (%p)
证明:类似上方,进行展开。
例题:余数之和
我们的思路是进行分段计算,每次求出一段的和,从而加快计算效率。
在这一段中,对k取模所得的商是相同的,我们就可以把这个商给提出来,再进行等差数列求和,最后减去商与数列和之积。
重点在于确定每一段的末端,需要进行判断
a-=(k/i)*(i+g(i))*(g(i)-i+1)/2;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//-----pre_def----
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
#define init_h memset(h, -1, sizeof h), idx = 0;
#define lowbit(x) x &(-x)
//---------------
ull a,n,k;
ull g(ull i){
ull tmp=k/i;
if(tmp==0)return n;//商为0
return min(n,k/tmp);//如过该值都大于n了,要进行减枝,避免计算超出范围的数据
}
int main(){
cin>>n>>k;
a+=n*k;
for(ull i=1;i<=n;i=g(i)+1){
a-=(k/i)*(i+g(i))*(g(i)-i+1)/2;
}
cout<<a;
}