1.同余方程
给定a,b,求满足求满足ax≡1(mod mod b)的最小x。
一开始能得到: 求 ax mod b=1 时 x的最小值 想暴力来着发现不对劲 然后趁机会推了一遍gcd,……然后听到了一个叫做扩展欧几里得的东西
扩展欧几里得:模板:
long long exgcd(long long a,long long b,long long& x,long long& y)
{
if(!b)
{
x=1;
y=0;
return a;
}
long long r=exgcd(b,a%b,y,x);
y-=a/b*x;
return r;
}
对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然
存在整数对 x,y ,使得 gcd(a,b)=ax+by。
设 a>b。
1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
2,a>b>0 时
设
ax1+by1=gcd(a,b);
a
x
1
+
b
y
1
=
g
c
d
(
a
,
b
)
;
bx2+ (a mod b)y2= gcd(b,a mod b);
gcd(a,b) = gcd(b,a mod b);
则:ax1+ by1= bx2+ (a mod b)y2;
即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
说明: a-[a/b]*b即为mod运算。[a/b]代表取小于a/b的最大整数。
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
根据恒等定理得:x1=y2; y1=x2- [a / b] *y2;
……
最后再把问题转化成 ax+by=1 求x的最小解
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m;
void fun(int n,int m,int &x,int &y)
{
if (!m)
{
x=1;
y=0;
return;
}
//cout<<m<<' '<<n%m<<' '<<' '<<y<<' '<<x<<"\n";
fun(m,n%m,y,x);
y-=n/m*x;
//cout<<m<<' '<<n%m<<' '<<' '<<y<<' '<<x<<" 后面\n";
return;
}
int main()
{
freopen("mod.in","r",stdin);
freopen("mod.out","w",stdout);
scanf("%d%d",&n,&m);
int b=m,x,y;
fun(n,m,x,y);
printf("%d",(x+b)%b);
return 0;
}
2.借教室
做的时候想了很多方法 独独没有想到正解二分 可能还是我太菜的原因吧
分块可以做但是会超时
线段树则很快了
线段树
题面:给出n天,每天提供ai个教室,有m个请求,从si到ti每天借di个教室,能满足所有,输出0,不能输出-1和第一个不满足的要求编号
很明显看出来是区间修改,很自然想到线段树‘update里要记得写pushdown哦~
#include<cstdio>
#include<algorithm>
#define maxn 1110000
using namespace std;
int num[4*maxn];
long long classroom[4*maxn];
int d[maxn],b[maxn],t[maxn];
int a[maxn];
int n,m;
void update(int data){
num[data]-=classroom[data];
classroom[2*data]+=classroom[data];
classroom[2*data+1]+=classroom[data];
classroom[data]=0;
}
void add(int data,int l,int r,int ll,int rr,int x)
{
update(data);
if (l>rr || r<ll)return;
if (l>=ll && rr>=r)
{
classroom[data]+=x;
update(data);
return;
}
int mid=(l+r)>>1;
add(2*data,l,mid,ll,rr,x);
add(2*data+1,mid+1,r,ll,rr,x);
num[data]=min(num[2*data],num[2*data+1]);
}
void build(int data,int l,int r){
if (l==r)
{
num[data]=a[l];
return;
}
int mid=(l+r)>>1;
if (l<=mid) build(2*data,l,mid);
if (mid<r) build(2*data+1,mid+1,r);
num[data]=min(num[2*data],num[2*data+1]);
}
int main(){
freopen("classroom.in","r",stdin);
freopen("classroom.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
for (int i=1;i<=m;i++)
scanf("%d%d%d",&d[i],&b[i],&t[i]);
for (int i=1;i<=m;i++){
add(1,1,n,b[i],t[i],d[i]);
if (num[1]<0){
printf("-1\n%d",i);
return 0;
}
}
printf("0");
return 0;
}
3.疫情控制
不多说,二分加贪心的图论
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=211000;
typedef long long LL;
struct Node{
int j,v,next;
}e[maxn];
struct NODE{
int n1;
LL n2;
bool operator < (const NODE &b)const{
return n2<b.n2;
}
}b[maxn],c[maxn];
bool bo[maxn];
int a[maxn];
int fa[maxn][25];
LL len[maxn][25];
int id[maxn];
int n,m,cnt1,cnt2,NodeCnt=0;
void addedge(int u,int v,int w){
int p=++NodeCnt;
e[p].j=v;e[p].v=w;e[p].next=a[u];
a[u]=p;
}
void dfs(int u){
for (int p=a[u];p;p=e[p].next){
int j=e[p].j;
if (j!=fa[u][0]){
fa[j][0]=u;
len[j][0]=e[p].v;
dfs(j);
}
}
}
void dfs2(int u){
if (bo[u])return;
bool done=true,first=true;
for (int p=a[u];p;p=e[p].next){
int j=e[p].j;
if (j!=fa[u][0]){
dfs2(j);
done=false;
if (!bo[j])first=false;
}
}
if (u!=1 && first && !done)bo[u]=true;
}
bool check(long long time){
memset(bo,0,sizeof(bo));cnt1=cnt2=0;
memset(c,0,sizeof(c));
memset(b,0,sizeof(b));
for (int i=1;i<=m;i++){
int up=id[i];
LL tt=time;
for (int j=19;j>=0;j--)
if (fa[up][j] && tt>=len[up][j]){
tt-=len[up][j];
up=fa[up][j];
}
if (up!=1)bo[up]=true;
else {
c[++cnt1].n2=tt;
up=id[i];
for (int j=19;j>=0;j--)
if (fa[up][j]>1)up=fa[up][j];
c[cnt1].n1=up;
}
}
dfs2(1);
for (int p=a[1];p;p=e[p].next){
int j=e[p].j;
if (!bo[j])b[++cnt2].n1=j,b[cnt2].n2=len[j][0];
}
if (cnt1<cnt2)return false;
sort(c+1,c+1+cnt1);
sort(b+1,b+1+cnt2);
int j=1;
b[cnt2+1].n2=0x7fffffff;
for (int i=1;i<=cnt1;i++){
if (!bo[c[i].n1])bo[c[i].n1]=true;
else{
if (c[i].n2>=b[j].n2)bo[b[j].n1]=true,j++;
}
while (bo[b[j].n1])j++;
}
return j>cnt2;
}
int main(){
freopen("blockade.in","r",stdin);
freopen("blockade.out","w",stdout);
scanf("%d",&n);
LL r=0;
for (int i=1;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
r+=z;
addedge(x,y,z);
addedge(y,x,z);
}
dfs(1);
for (int j=1;j<20;j++)
for (int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1],len[i][j]=len[fa[i][j-1]][j-1]+len[i][j-1];
scanf("%d",&m);
for (int i=1;i<=m;i++)scanf("%d",&id[i]);
LL l=0;
while (l<r){
LL mid=(l+r)>>1;
if (check(mid))r=mid;
else l=mid+1;
}
printf("%lld",l);
return 0;
}