• Codeforces 1316C


    题目大意:

    给定两个多项式长度 n 和 m ,再给定每一项的系数,由常数项到最高次项

    保证多项式所有项系数的最大公约数为 1

    再给定一个质数 p

    问两个多项式相乘后得到的第三个多项式中

    哪一项的系数不是 p 的倍数,输出这个项的x的幂次(下标)

    存在多个答案时,输出任意一个

    解题思路:

    从 “保证多项式所有项系数的最大公约数为 1” 可得题目一定有解(反正没说无解的输出情况略略略)

    根据x的次数关系可以得到第三个多项式的系数表达式为

    求的是满足 c[ t ] % p != 0 时 t 的值

    首先知道的是,p 是个质数

    只有两个数 α 和 β 同时满足 α mod p ≠ 0 并且 β mod p ≠ 0 时

    那么两数之积 α*β mod p ≠ 0 才成立

    相反,只要有一个数不满足 mod p ≠ 0 ,那么乘法就相当于多个这个数相加,明显结论不成立

    所以我们要在 a 数列和 b 数列中找不是p倍数的数出现的位置

    假设找到在 a 数列中位置 i 的数和 b 数列中位置 j 的数满足条件

    那么对应在 c 数列中的位置为 i+j

    但是需要注意,有可能目前 a[ i ]*b[ j ] %p 不等于0,但是 c 数列的表达式是一个多项式,有可能其他项 %p 后与我们找到的 a[ i ]*b[ j ]%p 得到的值正好凑成了p,这样的话这个 i+j 无法成为答案

    所以,我们需要保证 c 数列中 i+j 这个位置,除了 a[ i ]*b[ j ] 这一项以外,其他项不能出现 %p ≠ 0 的情况(事实上出现是可以出现的,只要保证取模后相加不是p的倍数即可,但是处理起来很麻烦,又因为两个数列中一定存在某些项不是p的倍数,所以这里直接贪心)

    想到的只有以下两种情况能够保证:

      ①:i 和 j 这两个位置的数分别是 a 数列和 b 数列中第一个出现的不是 p 倍数的数

      ②:i 和 j 这两个位置的数分别是 a 数列和 b 数列中最后一个出现的不是 p 倍数的数

    证明①:

    c[ i+j ] 的构成为 ...+ a[ i-1 ]*b[ j+1 ] + a[ i ]*b[ j ] + a[ i+1 ]*b[ j-1 ] +...

    因为 i 是 a 数列中第一个出现的不是 p 倍数的数

    所以 a[ i-1 ] , a[ i-2 ] ,... 都是 p 的倍数,与任何数相乘都还是p的倍数,所以左边划掉

    因为 j 是 b 数列中第一个出现的不是 p 倍数的数

    所以 b[ j-1 ] , b[ j-2 ] ,... 都是 p 的倍数,与任何数相乘都还是p的倍数,所以右边划掉

    只剩下中间一项不是 p 的倍数了,i+j 能够成为答案

    证明②:

    c[ i+j ] 的构成为 ...+ a[ i-1 ]*b[ j+1 ] + a[ i ]*b[ j ] + a[ i+1 ]*b[ j-1 ] +...

    因为 i 是 a 数列中最后一个出现的不是 p 倍数的数

    所以 a[ i+1 ] , a[ i+2 ] ,... 都是 p 的倍数,与任何数相乘都还是p的倍数,所以右边划掉

    因为 j 是 b 数列中最后一个出现的不是 p 倍数的数

    所以 b[ j+1 ] , b[ j+2 ] ,... 都是 p 的倍数,与任何数相乘都还是p的倍数,所以左边划掉

    只剩下中间一项不是 p 的倍数了,i+j  能够成为答案

    代码很简单(966ms / 1500ms)

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        int n,m,p,i,d,p1=-1,p2=-1;
        cin>>n>>m>>p;
        for(i=0;i<n;i++){
            cin>>d;
            if(d%p/* &&p1!=-1 */)//可加可不加,加了就是取第一项,不加取最后一项
                p1=i;
        }
        for(i=0;i<m;i++){
            cin>>d;
            if(d%p/* &&p2!=-1 */)
                p2=i;
        }
        cout<<p1+p2<<'
    ';
        
        return 0;
    }

    题外话:

    代码简单归简单,但是数据好像有点多,这点代码量跑了近 2/3 的时限

    于是我开了下io外挂

    ……

    没错,程序用时暂时全服第一了(划掉)(78ms)

    但这不重要,开心就好

  • 相关阅读:
    gridview列的汇总
    windows phone 页面传值(7)
    windows phone 获取手机图片库中图片(4)
    windows phone 使用相机并获取图片(3)
    windows phone 页面导航(6)
    windows phone 三种数据共享的方式(8)
    windows phone 独立存储空间的操作 (2)
    ref 和out传参的不同
    Web Service 实例
    关于DataList,Repeater,GridView的一些问题!! joe
  • 原文地址:https://www.cnblogs.com/stelayuri/p/12424150.html
Copyright © 2020-2023  润新知