歌名 - 歌手
0:00

    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;
    		}
    	}
    }
    
    posted @ 2018-05-23 21:48  无尽的蓝黄  阅读(133)  评论(0编辑  收藏  举报