一.工具篇
数论定理:
1.卢卡斯定理求大组合数:卢卡斯定理
2.中国剩余定理求同余方程的解:中国剩余定理
3.费马大定理和勾股数:费马大定理和勾股数
4.费马小定理求逆元:
费马小定理(要求:模数p为素数,且a 与 p互质即gcd(a,p) == 1)
由费马小定理知: a^(p-1) ≡ 1(mod p)即 a^(p-1)%p = 1
已知:a*inv(a)%p = 1
所以:a*inv(a)%p = a^(p-1)%p
则:inv(a)%p = a^(p-2)%p
于是这里用到快速幂 + 费马小定理来求逆元。
5.斯特林公式求高位乘阶:斯特林公式----求高阶乘阶及其位数
6.欧拉函数求1-n中与n互质的数的个数 : 欧拉函数
7.秦九昭算法化简多项式求解:秦九昭算法
素数相关:
1.素数筛法 : 埃拉托斯尼筛法nlogn + 欧拉筛法n
求解相关:
1.高斯消元法解线性方程组:高斯消元法
2.欧几里得算法和拓展欧几里得算法求ax+by=c的通解:拓展欧几里得
组合数学:
1.康拓展开和康拓逆展开:康拓展开和康拓逆展开
2.关于逆元:逆元及其求法
3.求组合数:求组合数的各种姿势
其他:
1.快速幂防溢出:x^y%mod
LL pow(LL x,LL y,int mod){
x%=mod;
LL ans = 1;
while(y){
if(y&1)ans = (ans*x)%mod;
y>>=1;
x = (x*x)%mod;
}
return ans;
}
2.快速乘防溢出:(x*y)%mod
LL Multi(LL a,LL b,LL mod){
LL ans = 0;
a%=mod;
while(b){
if(b&1)ans = (ans+a)%mod;
b>>=1;
a = (a + a)%mod;
}
return ans;
}
3.整数所有位置上数字之和若可以被3整除,则该整数可以被三整除
4.求最大公约数和最小公倍数
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);//最大公约数
}
int k = a*b/gcd(a,b);//最小公倍数
二.数论基本题型
1.除法表达式
(1)给出一个这样的除法表达式:X1/X2/X3/···/Xk,其中Xi是正整数。除法表达式应当按照从左到右的顺序求解,例如表达式1/2/1/2的值为1/4。但是可以在表达式中嵌入括号以改变计算顺序,例如表达式(1/2)/(1/2)的值为1.
INPUT
首先输入一个T,表示有T组测试数据,
每组数据输入占一行,第一个数字为k,后面跟k个数字为一个除法表达式,
输入保证合法。
判断能否使表达式的值为整数。k<=10000,Xi<=100000000.
OUTPUT
输出YES或NO
(2)分析:
表达式的值一定可以写成A/B的形式,假设表达式为整数,A=xp1*xp2*xp3*xp4*....*xpk
假设B=xq1*xq2*xq3*.....*xqn;
因为A/B为整数,则A为xq1*xq2*xq3*....*xqn的倍数,那么A肯定也是xq1的倍数,是xq2的倍数。。。。
那么(A/xq1 )*xq2*xq3*.....*xqn一定也是整数
所以不管怎样,表达式都能化成分母只有一个因子的样子,而我们发现,X2是一定位于分母上的!所以最终我们只需要判断X1*X3*X4*.....*Xk/X2是否为整数即可判断整个表达式!
代码:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
int X1,X2,x;
scanf("%d",&X1);
if(n==1){printf("Yes\n");continue;}
scanf("%d",&X2);
X2/=gcd(X1,X2);
for(int i = 2;i<n;i++){
scanf("%d",&x);
if(X2!=1){
X2/=gcd(X2,x);//约去多个数的最大公约数直到为1
}
}
if(X2==1)printf("Yes\n");
else printf("No\n");
}
return 0;
}
2.求解模线性方程