[Avito Cool Challenge 2018] 小结 A,C,E+听来的B

[Avito Cool Challenge 2018] 小结 A,C,E+听来的B

前言

上次的Educational Codeforces Round 56 (Rated for Div. 2) 由于 \n 引发了一系列惨案,再加上题目也不是很难,在此就不赘述了手动滑稽,分数还是记录一下:1453 → 1385
这场Avito Cool Challenge 2018基本算是数学场吧,orz,虽然是合场,但是辣鸡本人还是只出了三个题。上来 2min A题莽了一发的时候还是有点忐忑的,但是大神们都很快,嘤嘤嘤,还好抓住了关键点。B题以为是握手定理,虽然解释的通,但是完全不会写,后来下场了问了队友才知道想复杂了,orz。C题拿到手一看就是组合数学嘛,(虽然队友说可以dp),但是逆元没写过啊啊啊啊阿,查资料加试错,60min 才写出来,而且WA了六发,本体得分最低。后来开D,也是很玄学了,明明下午CSP才了一个类似的最短路,居然题意没看懂,也是醉不行。不懂没关系,我们可以看后面的嘛, 90min 的时候码了一个优化的很弱的E,居然一发过了也是很忐忑。后面的时间,就是专心B了,无果。成绩记录 :1385→ 1492

A. Definite Game

题意
就是有一个数,不断减去和他互质的数,最后能得到的最小数是多少。样例给的很有迷惑性,实际上除了2,n和n-1都互质。
代码

int main()
{
    int n;
    scanf("%d",&n);
    if(n==2)
        printf("2\n");
    else
        printf("1\n");
}
C. Colorful Bricks

题意
有n块的砖头摆在一起,有m种颜料,染色后,有k块和左边的颜色不一样,有多少种不同的染色方法。
做法
非常经典的组合题,咳咳,的一个叠加。公式如下:
在这里插入图片描述
我们来分解一下,对于每一处的k,其实就是一处分界面,我们需要在n-1个缝隙之间,找到k个,这是非常经典的隔板法,然后,由k个隔板隔开的k+1段,需要染上相邻不同的颜色,第一块,有m种,剩下的都只有m-1种。
此外,还有一个点就是逆元的运用了,将除法的取模转化为乘法。
代码

long long inv[2005];
void get_inverse(long long n,long long p)
{
	long long i;
	inv[1]=1;
	for(i=2;i<=n;++i)
	  inv[i]=(p-p/i)*inv[p%i]%p;
}
int main()
{
    long long n,m,k;
    scanf("%lld%lld%lld",&n,&m,&k);
    long long ans = 1;
    get_inverse(n,mod);
    if(k==0)
    {
        printf("%d",m);
        return 0;
    }
    for(int i=1;i<=min(k,n-k-1);i++) //用min来控制了一下,可以去掉
    {
        ans= (ans*(n-i))%mod;
        ans= (ans*inv[i])%mod;
    }
    ans = (ans*m)%mod;
    for(int i=1;i<k+1;i++)
    {
        ans = (ans*(m-1))%mod;
    }
    printf("%lld\n",ans);
}

E. Missing Numbers

题意
给定一个数组的偶数位,求我们能否给出一个完整的数列,使得此数列的每一个前缀和都是平方数。
做法
数学归纳法推出,假设前2k为已经成立,将第2k+2加入到前缀和中,求出一个前2k+2项和的平方根的下限,判断前2k+1的前缀和是否为平方数,若不满足,则调整2k+2的前缀和的大小。给定退出循环的条件,因为两个平方和的差一定不能大于给定数的一半加一(此关系可以根据平方差公式和不等式关系推出)
做法

long long num[100010];
long long ans[100010];
int main()
{
    int n;
    scanf("%d",&n);
    long long sum = 0;
    long long tmp = 0;
    long long lasttmp = 0;
    for(int i=0;i<n/2;i++)
    {
        scanf("%d",&num[i]);
        sum += num[i];
        lasttmp = tmp;
        tmp = sqrt(sum)+1;
        while(true)
        {
            sum = tmp*tmp;
            long long diff = sum - num[i];
            long long sq = sqrt(diff);
            if(sq*sq==diff)
            {
                break;
            }
            tmp++;
            if(tmp>num[i]/2+1)
            {
                printf("No\n");
                return 0;
            }
        }
        ans[i] = tmp*tmp -num[i]- lasttmp*lasttmp;
        if(ans[i]>1e13)
        {
            printf("No\n");
            return 0;
        }
    }
    printf("Yes\n");
    for(int i=0;i<n/2;i++)
    {
        printf("%lld %lld ",ans[i],num[i]);
    }
    printf("\n");
}

后话

最近有点忙哈,B题就先咕咕咕了,基本思路是集合的数量查找,嘿嘿嘿,希望我biubiubiu学长不会看见,略略略

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值