layout: post
title: 洛谷试炼场 3-5数论 3-17 倍增
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 数论
- 洛谷
[P2152 SDOI2009]SuperGCD
思路
直接上python
a=int(input())
b=int(input())
while a!=0:
b%=a
k=a
a=b
b=k
print(b)
P1414 又是毕业季II
思路
把每个数sqrt时间分解因子,然后枚举因子个数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int a[maxn];
int num[maxn];
int mx[maxn];
void solve(int x){
for(int i=1;i<=sqrt(x);i++){
if(x%i==0){
a[i]++;
if(i*i!=x)a[x/i]++;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
cin>>n;
int mp=0;
for(int i=1;i<=n;i++){
int aa;
cin>>aa;
solve(aa);
mp=max(mp,aa);
}
for(int i=1;i<=n;i++){
while(a[mp]<i)mp--;
cout<<mp<<endl;
}
return 0;
}
P1313 计算系数
思路
直接递推
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=10007;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll dp[1100][1100];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int a,b,k,n,m;
cin>>a>>b>>k>>n>>m;
dp[0][0]=1;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++){
if(i)dp[i][j]=(dp[i][j]+dp[i-1][j]*a)%mod;
if(j)dp[i][j]=(dp[i][j]+dp[i][j-1]*b)%mod;
}
cout<<dp[n][m]<<endl;
return 0;
}
P1306 斐波那契公约数 (gcd(Fn,Fm)=F(gcd(n,m)))
思路
只要知道gcd(fn,fm)=F(gcd(n,m))然后用一下矩阵快速幂就行
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e8;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
typedef vector<ll>vec;
typedef vector<vec>mat;
mat mul(mat& A,mat &B){
mat C(A.size(),vec(B[0].size()));
for(int i=0;i<A.size();i++)
for(int k=0;k<B.size();k++)
if(A[i][k])
for(int j=0;j<B[0].size();j++)
C[i][j]=(C[i][j]+A[i][k]*B[k][j]%mod+mod)%mod;
return C;
}
mat Pow(mat A,ll n){
mat B(A.size(),vec(A.size()));
for(int i=0;i<A.size();i++)B[i][i]=1;
for(;n;n>>=1,A=mul(A,A))
if(n&1)B=mul(B,A);
return B;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
ll n,m;
cin>>n>>m;
n=__gcd(n,m);
if(n==1){
cout<<1<<endl;return 0;
}
mat solve(2,vec(2));
solve[0][0]=1;solve[0][1]=1;
solve[1][0]=1;solve[1][1]=0;
mat ex(2,vec(1));
ex[0][0]=1;ex[1][0]=1;
solve=Pow(solve,n-2);
solve=mul(solve,ex);
cout<<solve[0][0]<<endl;
return 0;
}
P1967 货车运输 (最大生成树+LCA)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e8;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m;
struct Edge{
int from,to,w;
bool operator <(const Edge a)const{
return this->w>a.w;
}
};
vector<Edge>edges;
int f[maxn];
vector<Edge>ve[maxn];
int find(int x){
return f[x]==x?f[x]:(f[x]=find(f[x]));
}
void unite(int a,int b){
int aa=find(a),bb=find(b);
if(aa>bb)f[aa]=bb;
else f[bb]=f[aa];
}
void kruskal(){
for(int i=0;i<=n;i++)f[i]=i;
for(int i=0;i<2*m;i++){
if(find(edges[i].from)!=find(edges[i].to)){
unite(edges[i].from,edges[i].to);
ve[edges[i].from].push_back(Edge{0,edges[i].to,edges[i].w});
ve[edges[i].to].push_back(Edge{0,edges[i].from,edges[i].w});
}
}
}
int mi[maxn][22],fa[maxn][22],dep[maxn];
void dfs(int now,int pre,int w,int deep){
fa[now][0]=pre;
mi[now][0]=w;
if(pre==0)mi[now][0]=inf,fa[now][0]=now;
dep[now]=deep;
for(auto i:ve[now]){
if(i.to==pre)continue;
dfs(i.to,now,i.w,deep+1);
}
}
void init(){
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++){
int p=fa[j][i-1];
fa[j][i]=fa[p][i-1];
mi[j][i]=min(mi[j][i-1],mi[p][i-1]);
}
}
int lca(int p,int q){
if(dep[p]<dep[q])swap(p,q);
int res=inf;
for(int i=20;i>=0;i--)
if(dep[fa[p][i]]>=dep[q])
res=min(res,mi[p][i]),p=fa[p][i];
if(p==q)return res;
for(int i=20;i>=0;i--){
if(fa[p][i]!=fa[q][i]){
res=min(res,mi[p][i]);
res=min(res,mi[q][i]);
p=fa[p][i];q=fa[q][i];
}
}
return min(res,min(mi[p][0],mi[q][0]));
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
edges.push_back(Edge{a,b,c});
edges.push_back(Edge{b,a,c});
}
sort(edges.begin(),edges.end());
kruskal();
for(int i=1;i<=n;i++){
if(f[i]==i){
dfs(i,0,0,0);
}
}
init();
int q;cin>>q;
while(q--){
int x,y;
cin>>x>>y;
if(find(x)!=find(y))cout<<-1<<endl;
else cout<<lca(x,y)<<endl;
}
return 0;
}
P1613 跑路 (倍增+floyd)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int d[100][100],n,m;
bool ok[100][100][100];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
memset(d,inf,sizeof(d));
cin>>n>>m;
while(m--){
int x,y;
cin>>x>>y;
d[x][y]=1;
ok[x][y][0]=true;
}
for(int log=1;log<=50;log++)
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(ok[i][k][log-1]&&ok[k][j][log-1]){
ok[i][j][log]=true;
d[i][j]=1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(d[i][j]>(d[i][k]+d[k][j])){
d[i][j]=d[i][k]+d[k][j];
}
cout<<d[1][n]<<endl;
return 0;
}