Luogu考前模拟Round2总结

       虽说除了第一题我都是听了题解才会做的吧。。但还是有一些值得我学习的地方。
1、欧拉-费马定理:
    a^∮p≡1(mod p)(a≠p)
∴ a在模p意义下的乘法逆元为:a^(p-1)!
     特殊地,若p为质数,则a的乘法逆元为a^(p-2)。
2、从一个n*m的矩阵的左下角走到其右上角的路径数为:C(n+m,n)
证:从矩阵的左下角到右上角,其必经过n+m条边,其中选出n条边是上下方向的,故其总数为C(n+m,n).
3、模运算减法中,输出答案时需要转成正的,虽然在运算过程中是没必要的。
4、做题的时候,运算过程一定要严谨而认真,以至于不会出错;比如说第三题,因为我把600*600算成了3600,以至于我WA了一下午。
代码:
T1
 
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
long long s[1000001];
int main(){
const int P=1000000007;
int n,m,p=1000000005,nm,i;
long long ans=1,t;
s[0]=1;
scanf("%d%d",&n,&m);
if(n<m)swap(n,m);
for(i=1,nm=n+m;i<nm;++i)
s[i]=s[i-1]*i%P;
ans=s[nm-1]*nm%P;
t=s[n]*s[m]%P;
while(p){
if(p&1)ans=ans*t%P;
t=(t*t)%P;
p>>=1;
}
cout<<ans;
}
T2
 
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
int f[500001],pred[500001],a[500001],color[500000],s[500000];
int main(){
int N,M,i,tot,x;
scanf("%d%d",&N,&M);
for(i=1,++N;i<N;++i)
scanf("%d",a+i),color[i]=a[i];
sort(color+1,color+N);
tot=unique(color+1,color+N)-color;
f[0]=1;
for(i=1;i<N;++i){
x=lower_bound(color+1,color+N,a[i])-color;
s[i]=(s[i-1]+f[i-1])%M;
f[i]=(s[i]-(pred[x]?s[pred[x]]:0))%M;
pred[x]=i;
}
printf("%d",(s[N-1]+f[N-1]-1+M)%M);
}
T3
 
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
int fa[400000],allsum[400000],onesum[400000],tot;
long long g[601][601];
struct ES{
int x,y;
long long w;
inline bool operator < (ES a)const{
return w<a.w;
}
}e[720000];
inline int find(int x){
return fa[x]!=fa[fa[x]]?fa[x]=find(fa[x]):fa[x];
}
int main(){
int M,N,T,i,j;
long long ans=0;
scanf("%d%d%d",&M,&N,&T);
for(i=0;i<M;++i)
for(j=0;j<N;++j)
scanf("%d",g[i]+j);
for(i=0;i<M;++i)
for(j=0;j<N;++j){
scanf("%hd",onesum+i*N+j);
fa[i*N+j]=i*N+j;
allsum[i*N+j]=1;
}
for(i=0;i<M;++i)
for(j=1;j<N;++j)
e[tot++]=(ES){i*N+j-1,i*N+j,abs(g[i][j-1]-g[i][j])};
for(i=1;i<M;++i)
for(j=0;j<N;++j)
e[tot++]=(ES){i*N+j,(i-1)*N+j,abs(g[i-1][j]-g[i][j])};
sort(e,e+tot);
for(i=0;i<tot;++i)
if(find(e[i].x)!=find(e[i].y)){
if(allsum[fa[e[i].x]]+allsum[fa[e[i].y]]>=T){
if(allsum[fa[e[i].x]]<T)
ans+=e[i].w*onesum[fa[e[i].x]];
if(allsum[fa[e[i].y]]<T)
ans+=e[i].w*onesum[fa[e[i].y]];
}
allsum[fa[e[i].y]]+=allsum[fa[e[i].x]];
onesum[fa[e[i].y]]+=onesum[fa[e[i].x]];
fa[fa[e[i].x]]=fa[e[i].y];
}
cout<<ans;
}

你可能感兴趣的:(数论,组合数学)