上午
题前~
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ld;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n,i>=a;i--)
#define clr(a) memset(a,0,sizeof(a));
ld eps=1e-9;
ll pp=1000000007;
void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
//读入数字>100万个 读入优化必备防身!现在只要998!!!
<1.>高精度
加法
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char a[1000000],c[1000000];
int len1,len2,len;
int b[1000000],e[1000000],ou[1000000];
int main() {
ios::sync_with_stdio(false);
cin>>a;
len1=strlen(a);
for(int i=len1-1;i>=0;i--)
b[len1-i]=a[i]-'0';
cin>>c;
len2=strlen(c);
for(int i=len2-1;i>=0;i--)
e[len2-i]=c[i]-'0';
len=max(len1,len2);
for(int i=1;i<=len;i++){
ou[i]+=b[i]+e[i];
ou[i+1]+=ou[i]/10;
ou[i]%=10;
}
if(ou[len+1]!=0) len++;
for(int i=len;i>=1;i--)
cout<<ou[i];
return 0;
}
减法
删除前导0注意while
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char a[1000000],c[1000000];
int len1,len2,len;
int b[1000000],e[1000000],ou[1000000];
int main() {
ios::sync_with_stdio(false);
cin>>a;
len1=strlen(a);
for(int i=len1-1;i>=0;i--)
b[len1-i]=a[i]-'0';
cin>>c;
len2=strlen(c);
for(int i=len2-1;i>=0;i--)
e[len2-i]=c[i]-'0';
len=max(len1,len2);
for(int i=1;i<=len;i++){
ou[i]+=b[i]-e[i];
if(ou[i]<0) {
ou[i]+=10;
ou[i+1]--;
}
}
while(ou[len]==0) len--;
for(int i=len;i>=1;i--)
cout<<ou[i];
return 0;
}
乘法
注意i*j到i+j+1位上
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char a[1000000],c[1000000];
int len1,len2,len;
int b[1000000],e[1000000],ou[1000000];
int main() {
ios::sync_with_stdio(false);
cin>>a;
len1=strlen(a);
for(int i=len1-1;i>=0;i--)
b[len1-i]=a[i]-'0';
cin>>c;
len2=strlen(c);
for(int i=len2-1;i>=0;i--)
e[len2-i]=c[i]-'0';
len=len1+len2-1;
for(int i=1;i<=len1;i++)
for(int j=1;j<=len2;j++) {
ou[i+j-1]+=b[i]*e[j];
ou[i+j]+=ou[i+j-1]/10;
ou[i+j-1]=ou[i+j-1]%10;
}
while(ou[len+1]>0) len++;
for(int i=len;i>=1;i--)
cout<<ou[i];
return 0;
}
除法
分为高精度除以高精度(蒟蒻用不到)
高精度除以单精度
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char a[1000000],c[1000000];
int len1,len2,len;
int b[1000000],e[1000000],ou[1000000];
int main() {
ios::sync_with_stdio(false);
cin>>a;
len1=strlen(a);
for(int i=len1-1;i>=0;i--)
b[len1-i]=a[i]-'0';
cin>>c;
len2=strlen(c);
for(int i=len2-1;i>=0;i--)
e[len2-i]=c[i]-'0';
len=len1+len2-1;
for(int i=1;i<=len1;i++)
for(int j=1;j<=len2;j++) {
ou[i+j-1]+=b[i]*e[j];
ou[i+j]+=ou[i+j-1]/10;
ou[i+j-1]=ou[i+j-1]%10;
}
while(ou[len+1]>0) len++;
for(int i=len;i>=1;i--)
cout<<ou[i];
return 0;
}
优化:压位https://blog.csdn.net/ssssssay/article/details/52102173
<模意义下的运算>
- 一
求a的b次方
way 1 ? 分治
way 2 ? 快速幂
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int x,y,z;
calcfz(int a,int b,int c) {
if(b==1) return a;
int tmp=calc(a,b/2,c);
tmp=tmp*tmp%c;
if(b%2==1)tmp=tmp*a%c;
return tmp;
}
calcquc(int a,int b,int c) {
int tmp=1;
while(b!=0) {
if(b%2==1) tmp*=a;
a*=a;
b=b/2;
}
return tmp;
}
int main() {
ios::sync_with_stdio(false);
cin>>x>>y>>z;
cout<<calcquc(x,y,z);
return 0;
}
- 二.
费马小定理
a p互质 则a^(p-1)≡1(mod p)
应用:
取模的时候除法不能取模 例如(a/b)%p可以转化为a*b^(p-2)%p
求组合数 c[m][n]=n! / ((n-m)! * m!) %p = n! * ((n-m)!*m!) ^ p-2 %p =n!%p * (n-m)! %p * m!%p 预处理阶乘和阶乘的逆元(即p-2次方)
<求gcd>
int gcd(int a,int b) {
if(b==0) return a;
else return gcd(b,a%b);
}
求最小公倍数c=a/gcd(a,b)*b 先除再乘防爆栈
<筛素数>
&&分解质因数
……
<欧拉函数与欧拉定理>
先筛再phi
当p是质数 欧拉定理即费马小定理
————————————————————————————————————
下午
<矩阵乘法>
矩阵乘法不满足交换律!!!
int main() {
rep(i,1,m)
rep(j,1,n) {
c[i][j]=0;
rep(k,1,p)
c[i][j]+=a[i][k]*b[k][j];
}
}
<矩阵快速幂>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ld;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n,i>=a;i--)
#define clr(a) memset(a,0,sizeof(a));
ld eps=1e-9;
ll pp=1000000007;
void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
struct matrix {
int a[2][2];
};
//运算符重载
matrix operator *(matrix a,matrix b) {
matrix c;
rep(i,0,1)
rep(j,0,1) {
c.a[i][j]=0;
rep(k,0,1)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%pp;
}
return c;
}
int k;
int main(){
cin>>k;
matrix a;
a.a[0][0]=0;a.a[0][1]=1;
a.a[1][0]=1;a.a[1][1]=1;
matrix ans;
ans.a[0][0]=1;ans.a[0][1]=0;
ans.a[1][0]=0;ans.a[1][1]=1;
int b=k-1;
while(b){
if(b&1)ans=ans*a;
a=a*a;
b/=2;
}
int fk = (ans.a[0][0]+ ans.a[0][1])%pp;
cout<<fk<<endl;
//O(log B *2^3)
}
例题:蓝书P418例3
单位矩阵:主对角线(1,1)(2,2)……(n,n)是1 其余都是0
练习:luogu P4159
<特殊矩阵>
——上下三角矩阵经过乘法依然是上下三角矩阵
——分块乘完还是分块
——对角矩阵乘就是对角线上每个数乘
——对称矩阵可以只计算上三角然后结果对称过来省时
<高斯消元>
代码尚未get…………
his
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-1);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define fi first
#define sc second
ld eps=1e-9;
ll pp=1000000007;
ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
ll read(){
ll ans=0;
char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
//head
int n,m;
double a[100][100];
bool check(int k){
if(fabs(a[k][n+1])<eps)return 1;
rep(i,1,n)
if(fabs(a[k][i])>eps)return 1;
return 0;
}
int main(){
freopen("1.txt","r",stdin);
n=read();m=read();
// a_i,1 a_i,2 ... a_i,n a_i,n+1
rep(i,1,m)
rep(j,1,n+1)a[i][j]=read();
rep(j,1,m){
rep(k,1,n+1)cout<<a[j][k]<<" ";
puts("");
}
int flag=0;
rep(i,1,n){
int t=i;
while(a[t][i]==0 && t<=n)t+=1;
if(t==n+1){
flag=1;
continue;
}
rep(j,1,n+1)swap(a[i][j],a[t][j]);
double kk=a[i][i];
rep(j,1,n+1)a[i][j]/=kk;
rep(j,1,m)
if(i!=j){
double kk=a[j][i];
rep(k,1,n+1)
a[j][k]-=kk*a[i][k];
}
puts("------------");
rep(j,1,m){
rep(k,1,n+1)cout<<a[j][k]<<" ";
puts("");
}
}
if(flag){
rep(i,1,m)
if(!check(i)){
printf("No solution\n");
return 0;
}
printf("So many solutions\n");
}
}
<行列式>
计算:
高斯消元变成对角矩阵
对角连乘!?!??!
矩阵逆元:
若矩阵B*A=I 则称B为A的左逆元
有逆元前提:
矩阵行列式不为1
求左逆元:AI 同样操作 当A成为I I为左逆元
求右逆元:对每一列做高斯
<求生成树>