【比賽記錄】8.21 div2
阿新 • • 發佈:2020-08-22
A
選擇一個點\(B(x,0)\)使得\(|dis(A,B)-x|=k.\)
題目實際上就是找到一個最接近\(n\)的數,使得它可以分成兩個數\(a,b,\)使\(a-b=k.\)
我們考慮先分成一個可能的最小的數:\(0+k.\)這時兩邊\(+2\)就可以保證一定可以分成兩個數\(a,b\)使得\(a-b=k.\)
那麼我們直接對\(n-k\)的奇偶性討論即可。如果\(k>n\)直接輸出\(k-n\)即可。
#include<bits/stdc++.h> using namespace std; int T,n,k; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); if(k>n)printf("%d\n",k-n); else{ if((n-k)&1)puts("1"); else puts("0"); } } return 0; }
B
考慮貪心:\(a\)中的\(2\)先消耗\(b\)中的\(1,\)剩下的用\(a\)中的\(0\)儘量消耗。剩下的\(a\)中的\(1\)和\(b\)中的\(2\)匹配即可。
#include<bits/stdc++.h> using namespace std; int T; int a[4],b[4]; int main(){ scanf("%d",&T); while(T--){ int ans=0; scanf("%d%d%d",&a[0],&a[1],&a[2]); scanf("%d%d%d",&b[0],&b[1],&b[2]); int num=min(a[2],b[1]); ans+=2*num;a[2]-=num,b[1]-=num; num=min(a[0],b[2]);a[0]-=num,b[2]-=num; num=min(a[0],b[1]);a[0]-=num,b[1]-=num; num=min(a[0],b[0]);a[0]-=num,b[0]-=num; //a[0]finish num=min(a[1],b[1]);a[1]-=num;b[1]-=num; num=min(a[1],b[0]);a[1]-=num,b[0]-=num; num=min(a[2],b[2]);a[2]-=num;b[2]-=num; num=min(a[1],b[2]);ans-=num*2,a[1]-=num,b[2]-=num; cout<<ans<<endl; } return 0; }
C
由於題目中說的是最大公約數的序列中的最小數,且不會改變數字。所以,我們直接把可以換位置的數提出來,排好序再插進去,看看操作完的序列是不是單調不降序列即可。
#include<bits/stdc++.h> using namespace std; int T,n,a[200010],vis[200010]; int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); int fg=0,mi=(1<<30); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); mi=min(mi,a[i]); } for(int i=2;i<=n;++i){ if(a[i]<a[i-1]){ fg=1; break; } } if(!fg){ puts("YES"); for(int i=1;i<=n;++i)vis[i]=a[i]=0; continue; } fg=0; for(int i=1;i<=n;++i){ if(a[i]%mi==0)vis[i]=1; } vector<int>v;v.clear(); for(int i=1;i<=n;++i){ if(vis[i])v.push_back(a[i]); } sort(v.begin(),v.end()); vector<int>rev;rev.clear(); while((int)v.size()){ rev.push_back(v.back()); v.pop_back(); } for(int i=1;i<=n;++i){ if(vis[i])a[i]=rev.back(),rev.pop_back(); } for(int i=2;i<=n;++i){ if(a[i]<a[i-1]){ fg=1; break; } } if(fg)puts("NO"); else puts("YES"); for(int i=1;i<=n;++i)a[i]=vis[i]=0; } return 0; }
D
考慮貪心。因為給出了\(k\)的質因數分解結果,所以貪心顯然思路是出現次數最大的邊對應最大的質因子。
如果質因子數量小於\(n-1\)就補\(1,\)若大於則把最大的合併起來。
然後一遍\(dfs\)預處理\(siz\),注意次數\(siz*(n-siz)\)不能取模。這樣會使得排序結果錯誤。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
inline int add(int x,int y){return (x+y)%mod;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
const int MAXN=2e5+10;
int siz[MAXN],tot,head[MAXN],S;
struct edge{
int nxt,to;
}e[MAXN];
inline void link(int x,int y){
e[++tot].to=y;e[tot].nxt=head[x];
head[x]=tot;
}
int T,n,m,p[MAXN],ts[MAXN],t;
void dfs(int x,int fa){
siz[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(j==fa)continue;
dfs(j,x);siz[x]+=siz[j];
ts[++t]=siz[j]*(n-siz[j]);
S++;
}
}
void debug(){
for(int i=1;i<n;++i)cout<<p[i]<<" ";
puts("");
for(int i=1;i<=t;++i)cout<<ts[i]<<" ";
cout<<endl;
for(int i=1;i<=n;++i)cout<<siz[i]<<" ";
puts("");
cout<<"*"<<S<<endl;
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);int ans=0;t=0,S=0;
for(int i=1;i<n;++i){
int x,y;
scanf("%lld%lld",&x,&y);
link(x,y);link(y,x);
}
dfs(1,0);
sort(ts+1,ts+t+1);reverse(ts+1,ts+t+1);
scanf("%lld",&m);
for(int i=1;i<=m;++i)scanf("%lld",&p[i]);
while(m<n-1)p[++m]=1;
sort(p+1,p+m+1);
if(m>n-1){for(int i=n;i<=m;++i)p[n-1]=mul(p[n-1],p[i]);}
reverse(p+1,p+n);
for(int i=1;i<n;++i)ans=add(ans,mul(ts[i],p[i]));
printf("%lld\n",ans);
tot=0;for(int i=1;i<=n;++i)head[i]=0,siz[i]=0;
for(int i=1;i<n;++i)ts[i]=0;
for(int i=1;i<=m;++i)p[i]=0;
}
return 0;
}