codechef January Challenge 2017 简要题解

https://www.codechef.com/JAN17

Cats and Dogs

签到题

#include<cstdio>
int min(int a,int b){return a<b?a:b;}
int main(){
    int T,a,b,c;
    for(scanf("%d",&T);T;--T){
        scanf("%d%d%d",&a,&b,&c);
        puts(c%4==0&&c/4<=a+b&&c/4>=a+b-min(a,b*2)?"yes":"no");
    }
    return 0;
} 
View Code

Reservior

按题目要求模拟

#include<cstdio>
int T,n,m;
char s[1007][1007];
int main(){
    for(scanf("%d",&T);T;--T){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=m+1;++i)s[0][i]='A',s[n+1][i]='B';
        for(int i=1;i<=n;++i)scanf("%s",s[i]+1),s[i][0]=s[i][m+1]='A';
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                if(s[i][j]=='W'){
                    if(s[i][j-1]=='A'||s[i][j+1]=='A'||s[i+1][j]=='A')goto no;
                }else if(s[i][j]=='B'){
                    if(s[i+1][j]=='A'||s[i+1][j]=='W')goto no;
                }
            }
        }
        puts("yes");
        continue;
        no:puts("no");
    }
    return 0;
} 
View Code

Capital Movement

排序后用时间戳打标记然后暴力找未被标记的最值

Tourists in Mancunia

 求欧拉回路

Digits Cannot Separate

 f[i][j]表示考虑了1..i,分了j段所能得到的gcd的集合,用set维护,实际状态数很少,可以暴力转移

Chef and Circle

 二分答案,判定时枚举每一个点A,让一个指定半径的圆O绕点A转一周(A在圆上),记录其他点在圆内时对应的 射线AO 所处的方向区间,求一下某个方向最多被区间覆盖多少次即对应最多有几个点在圆内

Fantastic Four 

 随机求出10^6以内的每个数的任意一组解,然后线段树维护区间内数的积对应的解,可以按四平方和恒等式合并答案,常数较大,需要O(1)的快速乘

Sereja and BOX

 最大值可以贪心,最小值用dp

Sereja and Circles

这题比较坑。。没想到太好的写法。。

整点这个限制不重要,对答案影响在1以内,所以先不管

那么这时,能否得到得分ans,等价于正方形区域边长和每个圆的直径都增加ans后,能否将所有圆不相交地放入正方形

由于强制在线,没法二分答案,那么可以用随机数据本地找出一个自己的程序一般能比较保险出解的上界,然后把答案定下来,以此为目标分

实测表明,每次放球放在最低点(当然重力方向可以不是竖直向下)的效果很好。。这样能水到90~100分。。我写的是从左上向右下放,rank1写的貌似是将圆从四周向中间放再加一些优化

另外可以尝试区分第三、四类数据,但对总分影响较小

Coprime 6-tuples

 若已得到mod 359999意义下每个乘积的出现次数,则可以用 莫比乌斯反演 算出答案,注意特判0

359999=599*601,将mod 359999意义下的数用mod 599,601的值组成的有序对表示,则有(0,0),(0,b),(a,0),(a,b)四种形式,其中a,b非零,对非零的情况取离散对数,然后可以用二维fft求出每个乘积的出现次数,若a=0或b=0,可以直接暴力求解

原文地址:https://www.cnblogs.com/ccz181078/p/6298165.html