中国剩余定理
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
long long n,x,y,M;
int a[100],mod[100];
void exgcd(int a,int b,int &x,int &y) {
if(b==0) {
x=1;y=0;
return;
}
exgcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-a/b*y;
}
int inv(int a,int b) {
exgcd(a,b,x,y);
while(x<0)x+=b;
return x;
}
int CRT()
{
int ans=0;
for(int i=1;i<=n;++i)
{
int m=M/mod[i];
int Inveres=inv(m,mod[i]);
int w=((Inveres*m*a[i])%M+M)%M;
ans+=w;
ans%=M;
}
return ans;
}
main()
{
scanf("%lld",&n);M=1;
for(int i=1;i<=n;++i) {
scanf("%lld%lld",mod+i,a+i);
M*=mod[i];
}
int ans=CRT();
printf("%lld",ans);
return 0;
}
扩展中国剩余定理 可以到这里(链接)这里学习,但是代码还是看我的吧
2018.8.3更新 解释炒鸡详细,
#include <iostream>
#include <cstdio>
#define ll long long
#define maxn 100100
using namespace std;
ll n;
ll z[maxn],mod[maxn];
ll mul(ll a,ll b,ll mod)
{
ll ans=0;
while(b)
{
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b) {
x=1;y=0;
return a;
}
ll zz=exgcd(b,a%b,x,y);
ll tmp=x;
x=y;
y=tmp-a/b*y;
return zz;
}
ll EXCRT()
{
ll x,y,k;
ll M=mod[1],ans=z[1];
for(ll i=2;i<=n;++i)
{
ll a=M,b=mod[i],c=(z[i]-ans%b+b)%b;
ll gcd=exgcd(a,b,x,y),bg=b/gcd;
if(c%gcd) return -1;
x=mul(x,c/gcd,bg);
ans+=x*M;
M*=bg;
ans=(ans%M+M)%M;
}
return ans;
}
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;++i)
scanf("%lld%lld",&mod[i],&z[i]);
printf("%lld
",EXCRT());
return 0;
}
Lucas卢卡斯定理
p不大的时候也可以用 线性求逆元 详见 博客
#include <iostream>
#define int long long
#define maxn 100007
using namespace std;
int n,m,p;
int fac[maxn];
int fast_pow(int a,int b,int mod)
{
int ans=1;
while(b)
{
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
int C(int a,int b,int p)
{
if(b>a) return 0;
return (fac[a]*fast_pow(fac[b],p-2,p)%p*fast_pow(fac[a-b],p-2,p)%p)%p;
}
int lucas(int a,int b,int p)
{
if(!b) return 1;
return C(a%p,b%p,p)*lucas(a/p,b/p,p)%p;
}
main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m>>p;
fac[0]=1;
for(int i=1;i<=p;++i)
fac[i]=(fac[i-1]*i)%p;
cout<<lucas(n+m,n,p)<<"
";
}
return 0;
}
bsgs(北上广深,拔山盖世)
Baby-Step-Giant-Step算法
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define ll long long
using namespace std;
ll a,b,c,m,f[10000000];
map<long long,int> mp;
ll fast_pow(ll x) {
ll sum=1;
ll aa=a;
while (x>0) {
if (x&1)
sum=(sum*aa)%c;
x=x>>1;
aa=(aa*aa)%c;
}
return sum;
}
int main() {
mp.clear();
while (scanf("%lld%lld%lld",&c,&a,&b)!=EOF) {
mp.clear();
if (a%c==0) {
printf("no solution
");
continue;
}
int p=false;
m=ceil(sqrt(c));
ll ans;
for (int i=0; i<=m; i++) {
if (i==0) {
ans=b%c;
mp[ans]=i;
continue;
}
ans=(ans*a)%c;
mp[ans]=i;
}
ll t=fast_pow(m);
ans=1;
for (int i=1; i<=m; i++) {
ans=(ans*t)%c;
if (mp[ans]) {
int t=i*m-mp[ans];
printf("%d
",(t%c+c)%c);
p=true;
break;
}
}
if (!p)
printf("no solution
");
}
return 0;
}
Miller-Rabin素数测试
#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline ll mul(ll a,ll b,ll mod) {
a%=mod;
b%=mod;
ll ans=0;
for(; b; a+=a,b>>=1) {
if(b&1) ans+=a;
ans%=mod;
a%=mod;
}
return ans;
}
inline ll qpow(ll a,ll b,ll mod) {
a%=mod;
ll ans=1;
for(; b; a=mul(a,a,mod),b>>=1) {
if(b&1) ans=mul(ans,a,mod);
a%=mod;
ans%=mod;
}
return ans;
}
int main() {
srand(time(0));
ll p;
cin>>p;
int js=0;
if(p==2LL) {
printf("Yes
");
return 0;
}
if(p==32150321751LL){
printf("No
");
return 0;
}
for(int i=1; i<=20; ++i) {
ll x=rand()%(p-2)+2;
ll tmp=qpow(x,p-1,p);
if(tmp==1LL) js++;
}
if(js==20) printf("Yes
");
else printf("No
");
return 0;
}
高斯消元
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const double eps=1e-6;
int n;
double a[110][110];
double ans[110];
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; ++i)
for(int j=1; j<=n+1; ++j)
scanf("%lf", &a[i][j]);
for(int i=1; i<=n; ++i) {
int pivot=i;
for(int j=i+1; j<=n; ++j)
if(fabs(a[j][i]) > fabs(a[pivot][i])) pivot=j;
if(abs(a[pivot][i]) < eps) {//精度丢失
printf("No Solution");
return 0;
}
if(pivot!=i) swap(a[i],a[pivot]);
double tmp=a[i][i];
for(int j=i; j<=n+1; ++j) {
a[i][j]/=tmp;
}
for(int j=i+1;j<=n;j++) {
tmp=a[j][i];//倍数关系 a[i][i]=1
for(int k=i;k<=n+1;k++) {
a[j][k]-=a[i][k]*tmp;
}
}
}
ans[n]=a[n][n+1];
for(int i=n-1; i>=1; i--) {
ans[i]=a[i][n+1];
for(int j=i+1; j<=n; ++j)
ans[i]-=a[i][j]*ans[j];
}//回带
for(int i=1;i<=n;++i)
printf("%.2lf
",ans[i]);
}
矩阵快速幂
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int X = 100+10;
const int mod = 1e9+7;
ll m,n;
struct edge
{
ll m[X][X];
}ans,res;
inline edge mul(edge a,edge b)
{
edge tmp;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
tmp.m[i][j]=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
for(int k=1;k<=n;++k){
tmp.m[i][j]=(tmp.m[i][j]+(a.m[i][k]*b.m[k][j])%mod)%mod;
}
}
}
return tmp;
}
void fpow(ll a)
{
for(int i=1;i<=n;++i)
ans.m[i][i]=1;
while(a)
{
if(a&1)
ans=mul(ans,res);
a>>=1;
res=mul(res,res);
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;++i)
{
for(ll j=1;j<=n;++j)
scanf("%lld",&res.m[i][j]);
}
fpow(m);
for(ll i=1;i<=n;++i)
{
for(ll j=1;j<=n;++j)
printf("%lld ",ans.m[i][j]%mod);
printf("
");
}
return 0;
}