Codeforces Round #383 (Div. 2)

A. Arpa’s hard exam and Mehrdad’s naive cheat

题意

1378n 的末位数字, 0n109

分析

尾数的循环节, 6,8,4,2

HINT: 13780 需要特判

代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,a[] = {6,8,4,2};
    scanf("%d",&n);
    if(n == 0)  printf("1\n");
    else    printf("%d\n",a[n%4]);
}

B. Arpa’s obvious problem and Mehrdad’s terrible solution

题意

有n个数字分别为 a1,a2,,an (1ai105) ,问有多少组合使得 aiaj=x 成立

分析

由于 ai[1,105] ,故统计对应数字的个数

遍历 [1,105] ,通过 ix 计数

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 200000 + 1;
int cnt[N];
int main(){
    int n,x;
    scanf("%d %d",&n,&x);
    for(int i=0,a;i<n;i++)
        scanf("%d",&a), cnt[a]++;
    long long ans = 0;
    if(x){
        for(int i=0;i<100001;i++)
            if(cnt[i] && cnt[i^x])
                ans += (long long)cnt[i]*cnt[i^x];
    }else{  
        for(int i=0;i<100001;i++)
            ans += (long long)cnt[i] * (cnt[i]-1);
    }
    printf("%I64d\n",ans/2);
}

C. Arpa’s loud Owf and Mehrdad’s evil plan

题意

定义操作: Owf为x通过 xcrush[x]crush[crush[x]]y 其中转移t次

满足 ycrush[y]crush[crush[y]]x

问最小的t使得所有数 [1,n] 均满足上述操作

分析

若转移次数为奇数,则必须 x=y

若转移次数为偶数,则可取中间值使得 xy yx 均转移t次即可

求最小公倍数

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 100+10;
int crush[N],n,cnt;
bool vis[N];
bool dfs(int idx,int st){
    if(idx == st)   return true;
    if(vis[idx])    return false;
    vis[idx] = 1;   cnt++;
    dfs(crush[idx],st);
}
long long solve(){
    long long ans = 1;
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        cnt = 1;
        bool flag = dfs(crush[i],i);
        if(!flag)   return -1;
        if(cnt % 2 == 0)    cnt /= 2;
        ans = ans * cnt / __gcd(ans,(long long)cnt);
    }
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&crush[i]);
    printf("%I64d\n",solve());
}

D. Arpa’s weak amphitheater and Mehrdad’s valuable Hoses

Description

Mehrdad wants to invite some Hoses to the palace for a dancing party. Each Hos has some weight wi and some beauty bi . Also each Hos may have some friends. Hoses are divided in some friendship groups. Two Hoses x and y are in the same friendship group if and only if there is a sequence of Hoses a1,a2,,ak such that ai and ai+1  are friends for each 1i<k , and a1=x and ak=y .

Arpa allowed to use the amphitheater of palace to Mehrdad for this party. Arpa’s amphitheater can hold at most w weight on it.

Mehrdad is so greedy that he wants to invite some Hoses such that sum of their weights is not greater than w and sum of their beauties is as large as possible. Along with that, from each friendship group he can either invite all Hoses, or no more than one. Otherwise, some Hoses will be hurt. Find for Mehrdad the maximum possible total beauty of Hoses he can invite so that no one gets hurt and the total weight doesn’t exceed w.

题意

抽象成背包问题

背包容量为w,现在有若干组物品,每组若干件物品,每件物品的体积为wi,价值为 bi ,每组物品要么全选,要么最多选择一件。问在不超过背包容量的前提下,最大价值?

分析

分组的背包问题,详解见背包九讲

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1000 + 10;
const int V = 1000 + 10;
int w[N],b[N],dp[V],fa[N];
vector<int> vec[N];
int find(int x){
    return fa[x] = fa[x] == x ? x : find(fa[x]);
}
void Union(int x,int y){
    int fx = find(x),   fy = find(y);
    if(fx > fy) swap(fx,fy);
    fa[fy] = fx;    
}
int main(){
    int n,m,W;
    scanf("%d %d %d",&n,&m,&W);
    for(int i=1;i<=n;i++)   fa[i] = i;
    for(int i=1;i<=n;i++)   scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)   scanf("%d",&b[i]);
    for(int i=0,x,y;i<m;i++)    scanf("%d %d",&x,&y),   Union(x,y);
    for(int i=1;i<=n;i++)   vec[find(i)].push_back(i);
    for(int i=1;i<=n;i++){
        if(vec[i].size() == 0)  continue;
        for(int v=W;v;v--){
            int totW = 0,   totB = 0;
            for(int j=0;j<vec[i].size();j++){
                if(v >= w[vec[i][j]])
                    dp[v] = max(dp[v],dp[v-w[vec[i][j]]] + b[vec[i][j]]);   
                totW += w[vec[i][j]];
                totB += b[vec[i][j]];
            }
            if(v >= totW)
                dp[v] = max(dp[v],dp[v-totW] + totB);
        }
    }
    printf("%d\n",dp[W]);
}

E. Arpa’s overnight party and Mehrdad’s silent entering

题意

已知n对情侣,编号分别为 [1,2×n] 中的一个(保证一个编号对应一人)

问是否能对每个人分配食物Kooft或Zahre-mar,使得:

  1. 每个人都能分配到Kooft或Zahre-mar
  2. 每对情侣分配到的食物必然不同
  3. 对于任意连续的3个人,必然有两人的食物是不同的。(Note:编号2n视作与编号1相邻)

给出一种可行方案即可。

分析

感觉很神奇的题。竟然可以转化为二分图…

关键在于要点3。对连续3人,使得必然有一个人的食物与其他两人不同,则其可能方案为1 1 2, 1 2 1, 2 1 1其中12的整体替换对最终答案没有影响。通过枚举可能情况可以发现,对连续3人食物的要求,可以转化为求相邻两人的情况,即要点3可以看作是使得编号为i*2i*2+1的两人的食物不同

此时,该问题即可转换为二分图染色

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int E = N + N;
int n,a[N],b[N],cnt = 0,head[N*2],arr[N*2];
struct Edge{
    int to,nxt; 
}e[E*2];
void addedge(int u,int v){
    e[++cnt].nxt = head[u];
    e[cnt].to = v;
    head[u] = cnt;
}
bool dfs(int idx){
    for(int i=head[idx],to;i;i=e[i].nxt){
        to = e[i].to;
        if(arr[to]){
            if(arr[to] == arr[idx]) 
                return false;
            continue;
        }
        arr[to] = 3-arr[idx];
        if(!dfs(to))    return false;
    }
    return true;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d %d",&a[i],&b[i]), addedge(a[i],b[i]), addedge(b[i],a[i]);
    for(int i=1;i<=n;i++)
        addedge(i*2,i*2+1), addedge(i*2+1,i*2);
    bool flag = 1;
    for(int i=1;i<=2*n;i++)
        if(arr[i] == 0 && (arr[i] = 1) && !dfs(i)){
            flag = 0;   break;
        }   
    if(!flag)   printf("-1");
    else{
        for(int i=1;i<=n;i++)
            printf("%d %d\n",arr[a[i]],arr[b[i]]);  
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值