A. Distance and Axis
题意:
给出 n , k n,k n,k分别表示A点的位置和 a b s ( O B − A B ) abs({OB}-{AB}) abs(OB−AB)绝对值,现在让你找到点 B B B合题目要求
思路
分为 n ≤ k n\leq k n≤k
此时显然移动距离为 k − n k-n k−n
当 n > k n>k n>k时,显然需要把点 B B B放到 n n n和 k k k之间
又分为两种情况,如果 n n n为奇数, k k k为偶数那么需要一步操作。
如果 n n n为偶数 k k k为奇数那么也需要一步操作。
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n,k;cin>>n>>k;
if(n<=k){
cout<<(k-n)<<endl;s
}else{
if(k&1&&n%2==0){
cout<<1<<endl;
}else if(k%2==0&&n&1){
cout<<1<<endl;
}else cout<<0<<endl;
}
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
}
B. Ternary Sequence
题意
c i = { a i b i i f a i > b i 0 i f a i = b i − a i b i i f a i < b i c_i=\begin{cases} a_ib_i\quad ifa_i>b_i\\ 0\quad \quad ifa_i=b_i\\ -a_ib_i\quad ifa_i<b_i \end{cases} ci=⎩⎪⎨⎪⎧aibiifai>bi0ifai=bi−aibiifai<bi
根据a数组和b数组相应关系定为权值,求最大权值和
思路
我们看到要想有收入只能 a a a为2, b b b为1。那么我们只要最小化支出的情况也就是 a a a为1, b b b为2。
所以我们尽可能的减少消耗,就都用来减少 b b b数组的2
#include<bits/stdc++.h>
using namespace std;
void solve(){
int x1,y1,z1,x2,y2,z2;
cin>>x1>>y1>>z1>>x2>>y2>>z2;
int sum=0;
int t=min(x1,z2);
x1-=t,z2-=t;
int q=min(z1,z2);
z1-=q,z2-=q;
int r=min(z1,y2);
z1-=r,y2-=r;
int s=min(y1,z2);
sum=2*r-2*s;
cout<<sum<<endl;
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
}
C. Mere Array
题意
能否把他改为 n o n − d e c r e a s i n g non-decreasing non−decreasing序列
且更换时只能二者的 g c d gcd gcd为数组最小的数时可以更换
题意
显然因为他说的数组中最小的数,那么要更换二者的 g c d gcd gcd为该数就只能,每一个数和这个最小的数 g c d gcd gcd都为最小的数。
所以看一下不在位置上的 g c d ( x , m i n n ) gcd(x,minn) gcd(x,minn)是否为 m i n n minn minn即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],b[maxn];
void solve(){
int n;cin>>n;
int minn=1e9+10;
for(int i=1;i<=n;++i){
cin>>a[i];
minn=min(minn,a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
int flag=0;
for(int i=1;i<=n;++i){
if(a[i]!=b[i]){
if(__gcd(a[i],minn)!=minn)flag=1;
}
}
if(flag)cout<<"NO\n";
else cout<<"YES\n";
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
}
D. Maximum Distributed Tree
题意
给你n个点n-1条边的树,再给你m个素数 p i p_i pi其乘积为k,k很大。
让你给每条边赋权,且 n − 1 n-1 n−1条边权乘积为k
let ∑ i = 1 n − 1 ∑ j = i + 1 n f ( i , j ) \sum_{i=1}^{n-1}\sum_{j=i+1}^{n} f(i,j) ∑i=1n−1∑j=i+1nf(i,j)
思路
建图后跑dfs求出sz数组,然后考虑每条边被经过的次数 s z [ i ] ∗ ( n − s z [ i ] ) sz[i]*(n-sz[i]) sz[i]∗(n−sz[i])(为什么是这个公式,是因为他是一个全经过且不重边的图)
然后考虑m和n的大小,如果m过大就把p[n-1]增大,然后求和
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=2e5+10;
typedef long long ll;
#define int long long
int p[maxn],sz[maxn];
vector<int>edge[maxn];
void dfs(int u,int fa){
sz[u]=1;
for(auto v:edge[u]){
if(v==fa)continue;
dfs(v,u);
sz[u]+=sz[v];
}
}
void solve(){
int n;cin>>n;
for(int i=1;i<maxn;++i){
sz[i]=0;
edge[i].clear();
p[i]=1;
}
for(int _=1;_<n;++_){
int u,v;cin>>u>>v;
edge[u].push_back(v);
edge[v].push_back(u);
}
int m;cin>>m;
for(int i=1;i<=m;++i){
cin>>p[i];
}
if(m<n-1)m=n-1;
sort(p+1,p+1+m);
for(int i=n;i<=m;++i){
p[n-1]*=p[i];
p[n-1]%=mod;
}
dfs(1,0);
vector<int>val;
for(int i=2;i<=n;++i){
val.push_back(sz[i]*(n-sz[i]));
}
sort(val.begin(),val.end());
int ans=0;
for(int i=1;i<n;++i){
ans=(ans+(val[i-1]%mod*p[i]%mod)%mod)%mod;
}
cout<<ans<<endl;
}
signed main(){
int t;cin>>t;
while(t--){
solve();
}
}