Codeforces Round #716 (Div. 2)赛后补题

比赛地址

A. Perfectly Imperfect Array

  本题让我们判断数组中是否有子数组的乘积不是完全平方数。我们知道,对于任意的完全平方数,它们的乘积也是完全平方数,因为有数学公式\(a^2\cdot b^2\cdots n^2=(a+b+\cdots+n)^2\)。因此我们只需要判断数组中是否存在一个数不是完全平方数就可以了。
  注意使用\(sqrt()\)函数的精度问题,需要取整,不然会出现错误。

代码
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

void solve()
{
    int n;
    cin>>n;
    bool isOK=false;

    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        int t=(int)sqrt(x);
        if(t*t!=x) isOK=true;
    }

    cout<<(isOK?"YES":"NO")<<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int t=1;
    cin>>t;
    while(t--)
        solve();


    return 0;
}

B. AND 0, Sum Big

  本题有三个条件,最主要的条件就是序列中的每个数的与运算之后,结果等于零。通过观察我们知道,如果对于一个\(n=3,k=4\),我们能够使用的数为\(0,1,2,3,4,5,6,7\),能够得到的最大序列为\([0,7,7]\)。观察这个序列

\[0000=0\\ 0111=7\\ 0111=7\\ 0111=7\\ \]

如果我们想要得到的与结果为零的话,那么对于序列中的每一位,都至少应该有一个零。而我们每次最多只能修改一个元素,不然我们得到的序列的总和将会变小,可以自己动手算一下。一共有\(n\)个元素可以修改,可以移动的位置有\(k\)位,因此我们的结果就是\(n^k\)。这里就可以使用快速幂求解。

代码
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long LL;

const int mod=(int)1e9+7;

LL qmi(LL x,LL n)//快速幂模板
{
    LL res=1;
    while(n)
    {
        if(n&1) res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}

void solve()
{
    int n,k;
    cin>>n>>k;
    cout<<qmi(n,k)<<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int t=1;
    cin>>t;
    while(t--)
        solve();

    return 0;
}

C. Product 1 Modulo N

  本题要我们求出一个最长的序列(序列中的值范围在\((1,n-1)\)),使得序列中元素的乘积总和对\(n\)求模,得到的结果为\(1\)
  首先考虑什么样的数应该要被放到序列中。假设这个数为\(x\),如果\(gcd(x,n)!=1\),那么\(x\)与任何数的乘积都可以看成是一个数\(p\cdot gcd(x,n)\),这样的数加入到序列中,是不可能得到余数为\(1\)的结果的,因此我们应该将\(gcd(x,n)==1\)\(x\)加入到序列中。
  通过遍历,我们就得到一个序列,如果现在我们就输出的话,我们会发现这样是可以得到第二个样例的结果,但是第一个样例的结果就不对了。问题出在哪里呢?我们算法得到的样例一的结果序列是\({1,2,3,4}\),乘积结果为\(24\),而\(24%5==4\)显然不符合我们的条件。说明我们还需要删除一些元素,才能够得到乘积对\(5\)取模等于\(1\)的结果,由于我们想要得到的序列是最长的,因此我们其实只需要删去一个数就好了,删去的这个数就是\(4\),对取模运算两边同时除以\(4\)就可以得到余数是\(1\)的结果。于是我们就在原本算法的基础上增加对乘积取模结果的判断,如果不等于\(1\),说明我们需要删除一个等于乘积取模运算结果的数,并且这个数肯定与\(n\)互素。

代码
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>

using namespace std;

typedef long long LL;

int gcd(int a,int b)
{
    if(!b) return a;
    return gcd(b,a%b);
}

void solve()
{
    int n;
    cin>>n;

    vector<int> num;
    LL product=1;
    for(int i=1;i<n;i++)
    {
        if(gcd(i,n)==1)
        {
            num.push_back(i);
            product=product*i%n;
        }
    }

    if(product!=1)//如果乘积对n取模的结果不等于1的话,我们需要删除一个数
    {
        vector<int> ans;
        for(int i=0;i<(int)num.size();i++)
        {
            if(num[i]==product) continue;//删除,即不加入结果
            ans.push_back(num[i]);
        }
        num=ans;
    }

    cout<<(int)num.size()<<endl;
    for(auto c:num)
        cout<<c<<' ';

}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int t=1;
    //cin>>t;
    while(t--)
        solve();
    return 0;
}

D、E以后再填。

posted @ 2021-04-20 21:46  Daneii  阅读(80)  评论(0)    收藏  举报