T1
T1は、兄のいくつかの目に(一部)であってもよい(サブテーマに送られますしかし、私は唯一の10分を持っています)
このすべてに明らかな、我々は、係数のことを知って、ユークリッド対象の拡大です\(A、B \) 、解く方程式が必要です\(= Cの\によって斧+ ) とmake X | | + | Y \を( | \)の最小値を取得します
我々は、拡張ユークリッドを解決することができることを知っている\(AX + = GCDによって(A、B)\) 、および満たすC正の数がある場合(Cの\)\の%の\(GCDは(A、B)== 0 \) 、そう\(K = C / GCD( a、b)は\) 、その後、明らかに\(AKX + BKY = C \ ) ように\(のx =のKX、Y = KY \) 私たちは今、解決になる\を(| X | + | Y | \)
明らかにするための式\(斧は+ = GCD(によって 、B)\) と\((X-NB) NA + B(Y +)= xと\) と同等です私たちはヨーロッパの拡張を使用することができますリードは、この変更は、ソリューションの状態が得られているいくつかの特別な解決策を模索します。あなたは条件を満たすようにしたい場合は、我々はできるようにする必要があります\(X-NBは、\) 0に近いほど\(+ \ナy)を 0に近いです
仮定すると、\を(<B \) 、明らかであれば、Xの変化あなたは問題を単純化し、影響が比較的小さいために近い未知数のx 0、yは、あなたがそれを最適化することができることができますので、もしYの変化は非常に小さいので、それ(それはの初めに、ある\((<b)のスワップ(a、b)は\ IF) )
そして、あなたが行うことができます(実際には、上記の最適化ではないことができます)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long
using namespace std;
const int maxn=200010;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();};
return x*f;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(a%b==0){
x=1;y=0;return b;
}
ll d=exgcd(b,a%b,x,y),t;
t=y-a/b*x;
y=x;
x=t;
return d;
}
ll n,num[maxn],a,b;
int main()
{
// freopen("array.in","r",stdin);
// freopen("arrayown.out","w",stdout);
n=read();a=read();b=read();
if(a<b) a^=b^=a^=b;
ll d,x,y,ans=0;
d=exgcd(a,b,x,y);
a/=d;b/=d;
//这里一定要除哦 不然要WA
for(ll i=1;i<=n;i++){
num[i]=read();
if(abs(num[i])%d)
return printf("-1"),0;
ll X=x*(num[i]/d),Y=y*(num[i]/d);
swap(X,Y);
//x对应的系数大 y对应的系数小
//因为要改变y 使得y 尽量为接近零的数
if(Y<0){//使得Y变正
X-=b*((-Y)/a+1);
Y+=a*((-Y)/a+1);
}
X+=b*((Y)/a);
Y-=a*((Y)/a);
ans=ans+min(abs(X)+abs(Y),abs(X+b)+abs(Y-a));
}
printf("%lld",ans);
}
T2
GUGU区
#include<bits/stdc++.h>
#define L long long
#define vi vector<int>
#define pb push_back
using namespace std;
int n,m,w[200010],p;
L f[800010],g[800010];
struct orz
{
int a,b,p;
}x[100010];
inline bool cmp(orz a,orz b)
{
return a.a+a.b<b.a+b.b;
}
inline void down(int i)
{
f[i<<1]+=g[i];
g[i<<1]+=g[i];
f[i<<1|1]+=g[i];
g[i<<1|1]+=g[i];
g[i]=0;
}
inline L query(int i,int j,int k,int p)
{
if(j==k)
return f[i];
down(i);
if(p<=j+k>>1)
return query(i<<1,j,j+k>>1,p);
else
return max(f[i<<1],query(i<<1|1,(j+k>>1)+1,k,p));
}
inline void maxx(int i,int j,int k,int p,L q)
{
f[i]=max(f[i],q);
if(j!=k)
{
down(i);
if(p<=j+k>>1)
maxx(i<<1,j,j+k>>1,p,q);
else
maxx(i<<1|1,(j+k>>1)+1,k,p,q);
}
}
inline void add(int i,int j,int k,int l,int r,int p)
{
if(l<=j && k<=r)
{
f[i]+=p;
g[i]+=p;
}
else
{
down(i);
if(l<=(j+k>>1))
add(i<<1,j,j+k>>1,l,r,p);
if(r>(j+k>>1))
add(i<<1|1,(j+k>>1)+1,k,l,r,p);
f[i]=max(f[i<<1],f[i<<1|1]);
}
}
int main()
{
freopen("pair.in","r",stdin);
freopen("pair.out","w",stdout);
int i,j;
L k;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i].a,&x[i].b,&x[i].p);
w[++m]=x[i].a;
w[++m]=x[i].b;
}
sort(w+1,w+m+1);
m=unique(w+1,w+m+1)-w;
for(i=1;i<=n;i++)
{
x[i].a=lower_bound(w+1,w+m,x[i].a)-w;
x[i].b=lower_bound(w+1,w+m,x[i].b)-w;
}
sort(x+1,x+n+1,cmp);
for(p=1;p<m;p<<=1);
for(i=1;i<=n;i++)
{
j=min(x[i].a,x[i].b);
k=query(1,1,p,j)+x[i].p;
maxx(1,1,p,x[i].a,k);
if(x[i].b>x[i].a)
add(1,1,p,x[i].a+1,x[i].b,x[i].p);
}
printf("%lld\n",f[1]);
return 0;
}
T3
この質問は問題だ兄の目の前で、その後何ですが、長い時間のためのボード・こんにゃく・チューン(Mは、実際にはnと入力して理由をエッジ)
2つの特定の点の間の最初の移動距離のためemmm、あるいはそれらが直接接続され、あるいはそれらが直接接続されておらず、他のポイントから転送することによって(、唯一点以外の特別ポイントから転送されてもよいことに注意してくださいそれは、明らかにより劣って来て、別の特別なポイントから転送された場合に明らかに優れた特殊なポイントから転送されたのでので)
だから我々は、マルチソースの最短経路を鼓舞することができ、そしてそれは種類以上の特別なポイントから転送された場合、エッジの2つの端点のために、あなたはこの特別な2点ANSを更新することができます
証明用として。。
iとjのkは、隣接する拡張ポイントなしでソースポイントI、iとjポイントの拡大を証明することは困難ではない
I〜J kからの最適経路は、ソースkの拡大に行き、その後、歩いた場合の最もあり優秀。だから、これを行う
法律が正しいです。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
#define int long long
using namespace std;
const LL maxn=400010;
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node
{
int dis;
int pos;
bool operator <( const node &x )const
{
return x.dis < dis;
}
};
priority_queue<node> q;
LL n,m,p,spe[maxn],tot=1,from[maxn],dis[maxn],ans[maxn<<1];
LL fir[maxn<<1],nxt[maxn<<1],to[maxn<<1],val[maxn<<1],inque[maxn<<1];
void add(LL x,LL y,LL z){
nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;val[tot]=z;
nxt[++tot]=fir[y];fir[y]=tot;to[tot]=x;val[tot]=z;
}
void dij()
{
int rp,des;
for(int i=1;i<=p;i++)
q.push(node{0,spe[i]});
while(!q.empty())
{
node tmp=q.top();
q.pop();
int x=tmp.pos;int y=tmp.dis;
if(inque[x]) continue;
inque[x]=true;
for(rp=fir[x];rp;rp=nxt[rp])
{
des=to[rp];
if(dis[des]>y+val[rp]){
dis[des]=y+val[rp];
from[des]=from[x];
if(inque[des]==false)
{
q.push( ( node ){dis[des], des} );
}
}
}
}
}
signed main(){
// freopen("distance.in","r",stdin);
// freopen("distanceown.out","w",stdout);
n=read();m=read();p=read();
for(LL i=1;i<=p;i++)
spe[i]=read();
for(LL i=1,x,y,z;i<=m;i++){
x=read();y=read();z=read();
add(x,y,z);
}
for(LL i=1;i<=n;i++)
dis[i]=1e18,ans[i]=1e18;
for(LL i=1;i<=p;i++)
dis[spe[i]]=0,from[spe[i]]=spe[i];
dij();
for(LL x=1;x<=n;x++){
for(LL i=fir[x];i;i=nxt[i]){
LL y=to[i];
if(from[x]!=from[y])
ans[from[x]]=min(ans[from[x]],dis[x]+dis[y]+val[i]);
}
}
for(LL i=1;i<=p;i++)
{
if(i!=p)
printf("%lld ",ans[spe[i]]);
else printf("%lld\n",ans[spe[i]]);
}
return 0;
}
おそらくそれは、正直に言うことは難しいことではありません、それのタイトルだが、それはアヒルの暴漢の全体的な状況では、今日のほとんど差につながった問題の同じタイプだから