Codeforces Round #395 Div.1 C pacifist【JZOJ5449】Pacifist

題目

papyrus 喜歡謎題… 來解一道如何?
在你面前有一個被加密了的數組,其原數組是一個等差序列,你面前的則是將原數組中的所有數字都對m 取模再打亂後而得到的新數組
papyrus 給你出的謎題就是還原出原等差序列
保證數據有解,而且因爲papyrus 喜歡質數,所以他給你出的謎題中的m 一定是質數

分析

將a排序,當a[1]不是末項時,a[i]-a[1]一定有一個爲公差
枚舉公差d,
我們就可以通過等差數列和來求出首項a1,
我們通過a1和d來求出對應的等差數列平方和,na1²+n(n-1)d+n(n-1)(2n-1)d²
判斷是否符合。

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <queue>
using namespace std;
const int maxlongint=2147483647;
const int N=100005;
long long mo,a[N],sum,ny,n,su,ny1;
long long mi(long long x,int y)
{
    long long sum=1;
    for(;y;)
    {
        if(y&1) sum=sum*x%mo;
        x=x*x%mo;
        y>>=1;
    }
    return sum;
}
int main()
{
    freopen("pacifist.in","r",stdin);
    //freopen("pacifist.out","w",stdout);
    scanf("%lld%lld",&mo,&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),su=(su+a[i])%mo,sum=(sum+a[i]*a[i]%mo)%mo;
    sort(a+1,a+1+n);
    if(n==mo)
    {
        printf("0 1");
        return 0;
    }
    ny=mi(6,mo-2);
    ny1=mi(n,mo-2);
    for(int i=2;i<=n;i++)
    {
        long long d=(a[i]-a[1])%mo;
        if(!d) continue;
        long long a1=(2*su*ny1%mo-d*(n-1)%mo+mo)%mo*mi(2,mo-2)%mo;
        if((n*a1%mo*a1%mo+n*(n-1)%mo*(2*n-1)%mo*d%mo*d%mo*ny%mo+n*(n-1)%mo*d%mo*a1%mo)%mo==sum)
        {
            printf("%lld %lld",a1,d);
            return 0;
        }
    }
}
發佈了219 篇原創文章 · 獲贊 229 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章