Codechef July Challenge 2014部分题解

Dish Owner(并查集)

链接:http://www.codechef.com/JULY14/problems/DISHOWN/

题意分析:本题主要操作就是给出0 x y时,拥有第x道菜的厨师与拥有第y道菜的厨师pk,谁拥有的所有菜的其中一道菜(不一定是x或y)的分值比较高谁就获胜,并赢得loser的所有菜。即比较的是每个人分值最高的菜,所以对于非loser的人来说,他的分值最高的菜是不变的。综合题意用并查集易解。

#include <cstdio>

const int Maxn=10004;
int To[Maxn];
int val[Maxn];

int _find(int x){
    if(To[x]!=x)
        To[x]=_find(To[x]);     //路径压缩
    return To[x];
}

void _merge(int x,int y){
    int fx=_find(x);
    int fy=_find(y);
    To[fy]=fx;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
            To[i]=i;
        }
        int query;
        scanf("%d",&query);
        while(query--){
            int op;
            scanf("%d",&op);
            if(op==0){
                int x,y;
                scanf("%d%d",&x,&y);
                int fx=_find(x);    //获得x,y的父节点
                int fy=_find(y);
                if(fx==fy)
                    puts("Invalid query!");
                else{
                    if(val[fx]>val[fy]){
                        _merge(x,y);
                    }
                    else if(val[fx]<val[fy]){
                        _merge(y,x);
                    }
                }
            }
            else{
                int x;
                scanf("%d",&x);
                printf("%d\n",_find(x));
            }
        }
    }
    return 0;
}

Garden Game

链接:http://www.codechef.com/JULY14/problems/SGARDEN

题意分析:每响哨一次,处在位置i的人就移动到位置A[i],其中A[i]是不重复的。易知经过有限次响哨后,必定能够恢复到初始态;其中会出现多个互不相关的循环,求出每个循环的人数,计算其最小公倍数即可。注意结果会超过int的范围。

Python版:

#coding:utf8
def gcd(a, b):  #计算a,b的最大公约数
    if(b == 0):
        return a
    return int(gcd(b, a%b))

def fun(a, b):
    _gcd=gcd(a, b)
    product=a//_gcd*b   #用//运算符保证结果是整数
    return int(product)

T = int(input())
while(T > 0):
    n = int(input())
    num = [0]
    vis = [0]
    x = input()
    for i in x.split():
        num.append(int(i))
        vis.append(0)
    div = []
    st = 1
    #计算每个循环的人数
    while(st <= n):
        if(vis[st] == 0):
            mark=st
            vis[st]=1
            cnt=1
            nx=num[st]
            while(mark != nx):
                vis[nx] = 1
                nx = num[nx]
                cnt += 1
            if(cnt not in div):
                div.append(cnt)
        st += 1
    ans = 1
    for each in div:
        ans = fun(ans,each)
    print(int(ans%1000000007))
    T -= 1

C++版:

由于中间运算结果甚至会超出64位整形的范围,于是我采用了因数分解的方法。

#include <cstdio>
#include <cstring>
#include <set>
using namespace std;

const int Maxn=100005;
const int MOD=1000000007;
int num[Maxn];
bool vis[Maxn];
int prime[10000],primecount=0;
int totalcount[10000];

void getprime(){
    memset(vis,0,sizeof(vis));
    int i,j;
    for(i=2;i<100000;i++){
        if(!vis[i]){
            prime[primecount++]=i;
            for(j=i+i;j<100000;j+=i){
                vis[j]=1;
            }
        }
    }
}
void getdivsor(int param){
    int i;
    int num=param;
    int cnt;
    for(i=0;prime[i]<=num&&i<primecount;i++){
        if(num%prime[i]==0){
            cnt=0;
            while(num%prime[i]==0){
                cnt++;
                num/=prime[i];
            }
            if(totalcount[i]<cnt)
                totalcount[i]=cnt;
        }
    }
}
int main()
{
    getprime();//计算出10万内的所有质数
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
        }
        memset(vis,0,sizeof(vis));
        int st=1,nx,cnt,mark;
        set<int> div;
        while(st<=n){
            if(vis[st]==0){
                mark=st;
                vis[st]=1;
                cnt=1;
                nx=num[st];
                while(mark!=nx){
                    vis[nx]=1;
                    nx=num[nx];
                    ++cnt;
                }
                div.insert(cnt);
            }
            ++st;
        }
        long long ans=1;
        set<int>::iterator it;
        for(it=div.begin();it!=div.end();it++){
            getdivsor(*it);
        }
        for(int i=0;i<primecount;i++){
            long long temp=1;
            while(totalcount[i]>0){
                temp=(temp*prime[i])%MOD;
                totalcount[i]--;
            }
            ans=(ans*temp)%MOD;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Codechef July Challenge 2014部分题解,布布扣,bubuko.com

时间: 2024-12-25 12:11:47

Codechef July Challenge 2014部分题解的相关文章

Maximum number, GCD condition (codechef March Challenge 2014)

题目 : http://acm.bnu.edu.cn/v3/problem_show.php?pid=40489 最近做到的一道蛮有意思的题目(codechef现在的题目确实很赞了) 题意 :中文题面 (cc的一大好处就是有中文翻译,嘿嘿) 区间Max = max{a_i|gcd(a_i, g) > 1 && x <= i <= y} 做法 : 一开始我是用分块做的,复杂的O(m * sqrt(n) * C) C 是所含不同素数的个数, C大概最大只有6或7吧 然后裸裸的

Codechef March Challenge 2014——The Street

The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submissions for this problem are available. Read problems statements in Mandarin Chineseand Russian. The String street is known as the busiest street in Cod

[Codechef October Challenge 2014]刷漆

问题描述 Czy做完了所有的回答出了所有的询问,结果是,他因为脑力消耗过大而变得更虚了:).帮助Czy恢复身材的艰巨任务落到了你的肩上. 正巧,你的花园里有一个由N块排成一条直线的木板组成的栅栏,木板从左到右依次标号1到N.这N块木板中,有M块木板前面放着一桶油漆.油漆有不同的颜色,每种颜色可以由一个大写字母表示(A到Z).而你要求Czy用他的油漆刷子给栅栏刷上油漆. 已知Czy会选择一个前方放有油漆桶的木板开始他的任务.刷子蘸上油漆后,他开始随机地沿着栅栏走,他不会走出栅栏的范围.随机地走表示

CodeChef November Challenge 2014

重点回忆下我觉得比较有意义的题目吧.水题就只贴代码了. Distinct Characters Subsequence 水. 代码: 1 #include <cstdio> 2 #include <iostream> 3 #include <map> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #

[codechef July Challenge 2017] IPC Trainers

IPCTRAIN: 训练营教练题目描述本次印度编程训练营(Indian Programming Camp,IPC)共请到了 N 名教练.训练营的日程安排有 M 天,每天最多上一节课.第 i 名教练在第 Di 天到达,直到训练营结束才离开.第 i 名教练希望上 Ti 节课.要是少上了课,那么教练会感到扎心,每少上一节,扎心值就会加 Si.作为主办方,你希望最小化所有教练的扎心值之和.输入格式输入的第一行包含一个整数 T,代表测试数据的组数.接下来是 T 组数据.每组数据的第一行包含两个整数 N 和

[codechef July Challenge 2017] Chef and Sign Sequences

CHEFSIGN: 大厨与符号序列题目描述大厨昨天捡到了一个奇怪的字符串 s,这是一个仅包含'<'.'='和'>'三种比较符号的字符串.记字符串长度为 N,大厨想要在字符串的开头.结尾,和每两个字符之间插入一个正整数,共N + 1 个数.大厨希望插入数字之后,这些比较符号所表达的含义是正确的.举个例子,如果在'<'前后分别插入 a 和 b,那么应当有 a < b.对于'='和'>'也是类似的.大厨可以在 [1, P] 中任意选择数字插入,同一个数也可以被插入到多个位置.请你帮

Codechef December Challenge 2014 Chef and Apple Trees 水题

Chef and Apple Trees Chef loves to prepare delicious dishes. This time, Chef has decided to prepare a special dish for you, and needs to gather several apples to do so. Chef has N apple trees in his home garden. Each tree has a certain (non-zero) num

[codechef July Challenge 2017] Calculator

CALC: 计算器题目描述大厨有一个计算器,计算器上有两个屏幕和两个按钮.初始时每个屏幕上显示的都是 0.每按一次第一个按钮,就会让第一个屏幕上显示的数字加 1,同时消耗 1 单位的能量.每按一次第二个按钮,会让第二个屏幕上显示的数字加上第一个屏幕上显示的数字,同时消耗 B 单位的能量.初始时,计算器有 N 单位的能量.大厨想知道在能量限制下,第二个屏幕上最大可以出现的数字是多少?输入格式输入的第一行包含一个整数 T,代表测试数据的组数.接下来是 T 组数据.每组数据仅有一行,包含两个整数 N

codechef Row and Column Operations 题解

You are given an N × N grid initially filled by zeros. Let the rows and columns of the grid be numbered from1 to N, inclusive. There are two types of operations can be applied to the grid: RowAdd R X: all numbers in the row R should be increased by X