day2018.10.27模擬賽總結
今天應該是day9了吧,前幾天頹廢了沒有怎麼訂題寫部落格.
T1:
題目大意:給定一個序列,求序列中每一個數通過±a或者±b得到0的最小操作次數之和.
考場得分:100.
我覺得這道題猜結論很重要啊.
首先顯然每一個數都是獨立不影響其它數的次數的.
那麼看到操作有兩個數就很容易想到歐幾里得,由於求次數所以上擴歐.
我們可以將±a的操作次數設為,±b的操作次數設為,那麼就可以列出標準擴歐式.
然後就可以將問題轉化為求這個方程的一個整數解使得最小.很顯然只要讓兩個數分別為最小非負整數解和最大負整數解取min即可獲得答案.
程式碼如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; int n; LL ans,a,b,c,X,Y,g; LL exgcd(LL a,LL b,LL &x,LL &y){ if (b==0){ x=1;y=0; return a; } LL g=exgcd(b,a%b,x,y),tmp=x; x=y; y=tmp-a/b*y; return g; } LL d1(LL x){ LL y=(c-a*x)/b; return abs(x)+abs(y); } LL d2(LL y){ LL x=(c-b*y)/a; return abs(x)+abs(y); } Abigail into(){ scanf("%d%lld%lld",&n,&a,&b); g=exgcd(a,b,X,Y); LL h1=b/g,h2=a/g; for (int i=1;i<=n;i++){ scanf("%lld",&c); if (c%g){puts("-1");exit(0);} LL x=X*c/g,y=Y*c/g; LL g1=x%h1,g2=y%h2; g1+=g1<0?h1:0;g2+=g2<0?h2:0; LL now=min(min(d1(g1),d1(g1-h1)),min(d2(g2),d2(g2-h2))); ans+=now; } } Abigail outo(){ printf("%lld\n",ans); } int main(){ freopen("array.in","r",stdin); freopen("array.out","w",stdout); into(); outo(); return 0; }
T2:
題目大意:給定兩個序列a和b,讓你按照一個任意的順序排列a和b,但是原先的與到現在的順序必須是和,其中.現在然你求出在求出一個x序列,使得且不重複,使得,其中.
考場得分:10.
考場發現按照a,b排序都掛了,然後想離散化b後亂搞也掛了,最後還剩十分鐘寫了個暴力10分收場.
然後正解是按照a+b從大到小排序,然後神奇DP一發,再用線段樹優化一波即可.
具體怎麼做我不會沒聽懂
T3:
題目大意:給定一張無向帶權圖,以及p個特殊點編號為,讓你求出這個每一個特殊點到距離它最近的特殊點的距離.
考場得分:0.
由於幾天前一直在做最短路的題目,覺得這道題自己應該不會特別慘烈,然後發現這道題並沒有那麼簡單,然後棄掉了...
一開始我的思路是最短路樹來著,然後花了半個小時證明最短路樹是錯誤的,最短路樹上任意兩點在原圖上的最短路並不是在最短路樹上的兩點.
正解是一個十分容易的dijkstra,我們考慮從將每一個特殊點都入堆,然後跑一個dijkstra更新每個點的最短路,而且還要記錄一個點的是從哪個源點拓展過來的.
最後一步需要列舉所有的邊,如果邊的兩端是由不同源點拓展的,就更新這兩個點的答案,這一部具體可以看程式碼.
根據dijkstra演算法的原理,顯然這個演算法是正確的.時間複雜度.
程式碼如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=200000;
const LL INF=1LL<<60LL;
struct state{
int x,y;
LL v;
state(){x=y=0;v=0LL;}
state(int X,int Y,LL V){x=X;y=Y;v=V;}
bool operator > (const state &p)const{return v>p.v;}
};
priority_queue<state,vector<state>,greater<state> >q;
int n,m,p;
struct side{
int y,next,v;
}e[N*2+9];
int lin[N+9],top;
int u[N+9];
LL dis[N+9],ans[N+9];
int from[N+9],use[N+9];
void ins(int x,int y,int v){e[++top].y=y;e[top].v=v;e[top].next=lin[x];lin[x]=top;}
void dijkstra(){
for (int i=1;i<=n;i++)
dis[i]=INF,use[i]=0;
for (int i=1;i<=p;i++)
dis[u[i]]=0,from[u[i]]=u[i],q.push(state(u[i],u[i],0));
while (!q.empty()){
int t=q.top().x;q.pop();
if (use[t]) continue;
use[t]=1;
for (int i=lin[t];i;i=e[i].next)
if (dis[e[i].y]>dis[t]+e[i].v){
dis[e[i].y]=dis[t]+e[i].v;
from[e[i].y]=from[t];
q.push(state(e[i].y,from[e[i].y],dis[e[i].y]));
}
}
}
Abigail into(){
scanf("%d%d%d",&n,&m,&p);
for (int i=1;i<=p;i++) scanf("%d",&u[i]);
int x,y;
LL v;
for (int i=1;i<=m;i++){
scanf("%d%d%lld",&x,&y,&v);
ins(x,y,v);ins(y,x,v);
}
}
Abigail work(){
dijkstra();
for (int i=1;i<=n;i++) ans[i]=INF;
for (int i=1;i<=n;i++)
for (int j=lin[i];j;j=e[j].next)
if (from[i]^from[e[j].y]) ans[from[i]]=min(ans[from[i]],dis[i]+dis[e[j].y]+e[j].v);
}
Abigail outo(){
for (int i=1;i<=p;i++)
printf("%lld ",ans[u[i]]);
puts("");
}
int main(){
freopen("distance.in","r",stdin);
freopen("distance.out","w",stdout);
into();
work();
outo();
return 0;
}