Codeforces Round #709 B.Restore Modulo

问题描述:

传送门
在这里插入图片描述

输入说明:

在这里插入图片描述

输出说明:

在这里插入图片描述

SAMPLE INPUT:

6
6
1 9 17 6 14 3
3
4 2 2
3
7 3 4
3
2 2 4
5
0 1000000000 0 1000000000 0
2
1 1

SAMPLEOUTPUT:

19 8
-1
-1
-1
2000000000 1000000000
0

思路:

昨晚刚打的cf,本蒟蒻被这道题卡死了………………hack结束后看了眼别人的代码,发现自己到底是有多菜…………其实不是特别难的一道题,题意就是一个数组,里面的元素都满足(a[i-1]+c)%m=a[i]的关系(a[1]=s%m),题目给我们这些元素的大小,然后问是否存在这样的m和c能够满足数据的,如果有就输出其中的最大值。我自己的思路出了点问题,先判断是不是等差数列,如果是,那么直接输出,如果不是,那就不可能出现相邻的相同元素(这个应该很简单能够证得),然后算出每3个数可以满足的最大m值,然后对这些m值gcd,得到最大的m(测试用例的两个m值都可以得出),但是忘记了考虑当这数组只有两个元素时候的情况…………就第二个点都没过,直接wa了…………,然后事后发现其实我求m的方法也有问题,没有结合这三个数的大小关系进行求解,而是完全按照一种方法进行求解,测试用例没有出问题,但是test2的第一组数据就给了我下马威。(自己的代码还没改,改一改能a就也发上来)AC的代码如下,其中的思路在注释里(没有看懂的可以直接问我)

AC代码:

using namespace std;
int a[200001];
int main()
{
    std::ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while (t--)
    {
        int n;
        cin>>n;
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        int d=0;
        if(n>=2)//不加会在n<=2 的时候越界!
            d=a[1]-a[0];
        int fl=0;
        for(int i=0;i<n-1;i++)//检验数列中前后项的差值
        {
            if(a[i+1]-a[i]!=d)
            {
                fl=1;
                break;
            }
        }
        if(n==1||n==2||fl==0)//如果a1数列是个等差数列,或者a数列只有1/2个元素那就代表m的取值是没有限制的根据题目的要求,输出0
            cout<<0<<endl;
        else
        {
            d=0;
            int m=0;
            fl=0;
            for(int i=1;i<n-1;i++)//观察前后三项,根据不同的大小关系得到m和d(P.S:数列a单调的时候,当且仅当a是一个等差数列的时候才能够满足题意,而这一种在上面的操作已经考虑到了,所以在这里不用进行操作
            {
                if(a[i]<a[i-1]&&a[i]<a[i+1])//当中间项小于前后项的时候,这种情况一定是a[i-1]+c>m && (a[i-1]+c>m)% m =a[i] && a[i]+c=a[i+1]  (因为c是小于m的,所以不会出现a[i]+c>m ,求d的时候不需要再对m取模了)
                                                                                                                                                                    
                {
                    d=a[i+1]-a[i];
                    m=a[i-1]-a[i]+d;
                    break;
                }
                else if(a[i]>a[i-1]&&a[i]>a[i+1])//同上,思路是差不多的,只是大小关系发生了变化,一定是a[i-1]<a[i]<m,a[i]>a[i+1]的关系,按照这个关系求m和c即可
                {
                    d=a[i]-a[i-1];
                    m=a[i]-a[i+1]+d;
                    break;
                }
            }
            if(m!=0)//在上一步得到了潜在有可能的d和m后,遍历整个数组,确认这样的d和m能够满足数组中其他的三元组合,
            {
                for(int i=0;i<n-1;i++)
                {
                    if(a[i+1]!=(a[i]+d)%m)
                    {
                        fl=1;
                        break;
                    }
                }
            }
            if(a[0]>=m)//由于在上面的操作中我们都没有考虑a[0]的值是否小于m(如果大于m,那么这个m就不可能满足题目条件,所以这里做一个判断)
                fl=1;
            if(fl==1||m==0)//根据在上面进行的判断,得到存在这样的c和m还是不存在,从而进行输出。
                cout<<-1<<endl;
            else 
                cout<<m<<" "<<d<<endl;
        }
    }
    return 0;
}




被hack了,再思考思考

在这里插入图片描述

奇怪起来了

唯一改变的地方就是把循环中清空数组的操作memset改成了每次在循环中重新声明数组。
在这里插入图片描述
在这里插入图片描述
然后时间从超时,直接变成了340ms…………一时不知道为什么会这样…………

#include<bits/stdc++.h>
using namespace std;
int main()
{
    std::ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while (t--)
    {
        int n;
        cin>>n;
        int a[200001];
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        int d=0;
        if(n>=2)
            d=a[1]-a[0];
        int fl=0;
        for(int i=0;i<n-1;i++)
        {
            if(a[i+1]-a[i]!=d)
            {
                fl=1;
                break;
            }
        }
        if(n==1||n==2||fl==0)
        {
            cout<<0<<endl;
        }
        else
        {
            d=0;
            int m=0;
            fl=0;
            for(int i=1;i<n-1;i++)
            {
                if(a[i]<a[i-1]&&a[i]<a[i+1])

                {
                    d=a[i+1]-a[i];
                    m=a[i-1]-a[i]+d;
                    break;
                }
                else if(a[i]>a[i-1]&&a[i]>a[i+1])
                {
                    d=a[i]-a[i-1];
                    m=a[i]-a[i+1]+d;
                    break;
                }
            }
            if(m!=0)
            {
                for(int i=0;i<n-1;i++)
                {
                    if(a[i+1]!=(a[i]+d)%m)
                    {
                        fl=1;
                        break;
                    }
                }
            }
            if(a[0]>=m)
                fl=1;
            if(fl==1||m==0)
                cout<<-1<<endl;
            else
                cout<<m<<" "<<d<<endl;
        }
    }
    return 0;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值