Gym 101964 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018)

传送门

A.Numbers

 

B.Broken Watch 

     先考虑最简单的情况,就是a,b,c都相等的情况,这个时候答案显然只会跟n有关系,在n个线段里面选3个的情况就是C(n,3),其中有一部分不合法,这个时候考虑怎样是不合法的,现在设取三条边分别是x,y,z;当x经过y到达z的这个角的角度小于180度的时候,那么这个方案必然是不合法的,这样的话只需要确定x和z就可以确定一族不可行的方案,x和z可以夹1....[n/2](上取整)条边,也就是形成了[n/2](上取整)族答案,每一族的方案数分别是1...[n/2]。于是用总的方案数减去(1+2+3+...+[n/2](上取整))即可。这里的答案是对2^64取模,因此统计答案时要处理一下除法。
     对于a,b,c不相等的情况直接乘上A(3,1)或A(3,3)即可
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
int main(){

    int a,b,c;
    ll n;
    scanf("%d%d%d%llu",&a,&b,&c,&n);
    ll tmp=(n+1)/2;
    tmp-=2;
    ll ans=0;
    //特判除以6的情况
    ll tmp1=n,tmp2=n-1,tmp3=n-2;
    if(tmp1%2==0) tmp1/=2;
    else if((tmp2)%2==0) tmp2/=2;
    if(tmp1%3==0) tmp1/=3;
    else if(tmp2%3==0) tmp2/=3;
    else if(tmp3%3==0) tmp3/=3;
    ans=tmp1*tmp2*tmp3;
    
    ans-=n*(tmp*(tmp+1)/2);
    
    if(a!=b&&b!=c&&c!=a){//全都不相同
        ans*=6;
    }
    else if(a!=b||a!=c||b!=c){//有一个不同
        ans*=3;
    }
    printf("%llu\n",ans);
    return 0;
}
View Code

C.Tree

    首先,题目中的”使得最大值最小“这句话就非常符合二分的条件了。因此我们考虑对答案(两个黑点的最远的距离)进行二分。

    现在就要考虑如何进行check。

    对于每一个二分值k,我们考虑先用bfs遍历整颗树,然后利用bfs的性质(距离当前点的所有已bfs过且小于等于d的那些点,他们之间两两距离也小于等于k),找出满足距离等于k的对应的一个个点集。之后我们可以用dfs去遍历这些点集,判断点集中的黑点的个数与需要选取的黑点个数m之间的关系即可(如果数量>=n,则右指针左移动;反之左指针右移)。

#include <bits/stdc++.h>
#define maxn 105
using namespace std;
vector<int>vec[maxn];
int vis[maxn];//用vis数组去区分点的不同的集合
int a[maxn];
queue<int>que;
int n,m;
int ans=0;
int dfs(int now,int fa,int all,int dis){
    int res=a[now];
    if(dis==all) return res;
    for(auto &it:vec[now]){
        if(!vis[it]||it==fa) continue;
        res+=dfs(it,now,all,dis+1);
    }
    return res;
}
bool check(int k){//二分的check,本质上为一个bfs
    memset(vis,0,sizeof(vis));
    while(!que.empty()) que.pop();
    que.push(1);
    while(!que.empty()){//bfs选取部分点集
        int now=que.front();
        que.pop();
        vis[now]=1;
        int tmp=dfs(now,0,k,0);//通过dfs获取这个集合的黑点的个数
        if(tmp>=m) return 1;
        for(auto &it:vec[now]){
            if(vis[it]) continue;
            que.push(it);
        }
    }
    return 0;
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=0;i<n-1;i++){
        int from,to;
        scanf("%d%d",&from,&to);
        vec[from].push_back(to);
        vec[to].push_back(from);
    }
    int l=0,r=n;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
        //cout<<l<<" "<<r<<endl;
    }
    cout<<r<<endl;
}
View Code

D.Space Station


E.Fishermen

  


F.Min Max Convert


G.Matrix Queries


H.Modern Djinn


I.Inversion


J.Rabbit vs Turtle


K.Points and Rectangles

猜你喜欢

转载自www.cnblogs.com/Chen-Jr/p/9879980.html