Codeforces Round #665 (Div. 2)

A. Distance and Axis

题意:

给出 n , k n,k nk分别表示A点的位置和 a b s ( O B − A B ) abs({OB}-{AB}) abs(OBAB)绝对值,现在让你找到点 B B B合题目要求

思路

分为 n ≤ k n\leq k nk

此时显然移动距离为 k − n k-n kn

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=biaibiifai<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 nondecreasing序列

且更换时只能二者的 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 n1条边权乘积为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=1n1j=i+1nf(i,j)

思路

建图后跑dfs求出sz数组,然后考虑每条边被经过的次数 s z [ i ] ∗ ( n − s z [ i ] ) sz[i]*(n-sz[i]) sz[i](nsz[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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值