codeforces 1857(div3) E-F

Problem - E - Codeforces

稍微改变一下思路,对于每区间[l,r]单独计算该区间的贡献,对于区间[l,r]的贡献为r-l+1,然后就是计算对于任意的xi作为s能够造成的价值,对于比s小的数肯定就是[l,s],对于比s大的数肯定就是[s,r],分别对比s小的和大的统一计算,计算完后还有[s,s]本身,也就是要+1;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
int n,m,k;
ll a[N];
void solve(){
    cin>>n;
    vector<pii>v;
    fr(1,i,n){
        cin>>a[i];
        v.push_back({a[i],i});
    }
    sort(all(v));
    ll sum1=0,sum2=0;
    fr(1,i,n)sum2+=a[i];
    fr(0,i,n-1){
        sum2-=v[i].first;
        a[v[i].second]=i+(1LL*i*v[i].first-sum1)+(n-i-1)+(sum2-1LL*(n-i-1)*v[i].first)+1;
        sum1+=v[i].first;
    }
    fr(1,i,n)cout<<a[i]<<' ';cout<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    int t=1;
    cin>>t;
    fr(1,i,t){
        solve();
    }
}

Problem - F - Codeforces

解一元二次方程即可

对于ai+aj=x,ai*aj=y,可以稍微改变一下也就是ai=x-aj   ==> aj*x-aj*aj=y  ==>aj^2-aj*x+y=0;

最终得到了这样的一个一元二次方程a^2-a*x+y=0,求解分别统计数量即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
int n,m,k;
int a[N];
ll run(ll x){
    if(x<=0)return 0;
    ll l=1,r=x;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(mid>=x/mid||mid*mid>=x)r=mid-1;
        else l=mid+1;
    }
    return l;
}
void solve(){
    cin>>n;
    map<int,int>mp;
    fr(1,i,n)cin>>a[i],mp[a[i]]++;
    int q;
    cin>>q;
    while(q--){
        ll a,b;
        cin>>a>>b;
        ll x=a*a-4*b;
        ll res=run(x);
        if(res*res==x){
            if((a+res)%2||(a-res)%2){
                cout<<0<<' ';
            }else {
                ll ans1=(a+res)/2,ans2=(a-res)/2;
                if(ans1==ans2){
                    ll cnt=mp[ans1];
                    cout<<(cnt*(cnt-1))/2<<' ';
                }else{
                    ll cnt1=mp[ans1],cnt2=mp[ans2];
                    cout<<cnt1*cnt2<<' ';
                }
            }
        }else{
            cout<<0<<' ';
        }
    }
    cout<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    fr(1,i,t){
        solve();
    }
}

Problem - G - Codeforces

并查集+组合数+最小生成树

对于两棵子树a和b,已知子树a与子树b相连的边权为x,且a,b子树上所有的边权都不大于x,对于给定的s,对于所有子树a上的节点与子树b上的节点相连,只要边权超过x,不超过s就不影响原来的最小生成树.同样还不能有重边,所以总共最多可以增加(a的节点数*b的节点数-1)条边,对于每条边的取值范围(x,s],同时对于所有的边是个组合数问题,可以选择0条边,1条边,2条边.但是对于所有的边我再增加一种情况,除了取值范围(x,s]以外,再增加一种没有被选中的可能,这样就能够避免计算繁杂的组合数,也就是对于每条边总共有(s-x+1)种可能,总共有(a的节点数*b的节点数-1)条边

最后对于子树a和子树b的连接总共会产生(s-x+1)^(a的节点数*b的节点数-1)种可能,最后结合并查集计算答案,并查集合并的同时要统计子树大小;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=998244353;
string s;
int n,m,k;
int a[N];
int rea[N],cnt[N];
int find(int inx){
    if(rea[inx]==inx)return inx;
    return rea[inx]=find(rea[inx]);
}
ll pow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans*=a;
        b>>=1;
        a*=a;
        ans%=mod;
        a%=mod;
    }
    return ans;
}
void solve(){
    cin>>n>>k;
    vector<array<int,3>>v;
    fr(1,i,n){
        rea[i]=i;
        cnt[i]=1;
    }
    fr(2,i,n){
        int a,b,c;
        cin>>a>>b>>c;
        v.push_back({c,a,b});
    }
    sort(all(v));
    ll ans=1;
    for(auto cur:v){
        ll a,b,c;
        a=cur[1],b=cur[2],c=cur[0];
        if(c>=k)break;
        a=find(a),b=find(b);
        ans=ans*pow((k-c+1),1LL*cnt[a]*cnt[b]-1)%mod;
        cnt[a]+=cnt[b];
        rea[b]=a;
    }
    cout<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    fr(1,i,t){
        solve();
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值