您的位置:首页 > Web前端

E. Timofey and remoduling----数论及数学公式

2017-02-07 17:11 232 查看
E. Timofey and remoduling

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

Little Timofey likes integers a lot. Unfortunately, he is very young and can't work with very big integers, so he does all the operations modulo his favorite prime m.
Also, Timofey likes to look for arithmetical progressions everywhere.

One of his birthday presents was a sequence of distinct integers a1, a2, ..., an.
Timofey wants to know whether he can rearrange the elements of the sequence so that is will be an arithmetical progression modulo m,
or not.

Arithmetical progression modulo m of length n with
first element x and difference d is
sequence of integersx, x + d, x + 2d, ..., x + (n - 1)·d, each taken
modulo m.

Input

The first line contains two integers m and n (2 ≤ m ≤ 109 + 7, 1 ≤ n ≤ 105, m is
prime) — Timofey's favorite prime module and the length of the sequence.

The second line contains n distinct integers a1, a2, ..., an (0 ≤ ai < m) —
the elements of the sequence.

Output

Print -1 if it is not possible to rearrange the elements of the sequence so that is will be an arithmetical progression modulo m.

Otherwise, print two integers — the first element of the obtained progression x (0 ≤ x < m)
and its difference d (0 ≤ d < m).

If there are multiple answers, print any of them.

Examples

input
17 5
0 2 4 13 15


output
13 2


input
17 5
0 2 4 13 14


output
-1


input
5 3
1 2 3


output
3 4


题目链接:http://codeforces.com/contest/764/problem/E

题目的意思是是否有一个等差数列x,x+d...,x+(n-1)*d,使得其每个元素对m取模后,结果为a1,a2,...,an。如果有,输出首项x和公差d。如果没有,则输出-1,。多解输出一个即可。

cf的div2的第五题,比赛的时候我都没有看到这个题,赛后看了看这个题,发现比赛的时候 看了也是白看,完全没有思路,想了一会后,无奈,还是去搜了题解,本以为刚比完不会有大牛写博客,但是竟然有一篇,然后仔细研究了一个多小时,终于通了这个题,我的天。

先放上大牛的链接:http://blog.csdn.net/qq_33183401/article/details/54884972

大牛说是用的Q神的思路,Q神简直了,作为大连赛区就坐在我后面的队伍,表示我的压力山大啊。

思路还算简单,没有绕弯,主要就是两个数学公式的运用,然后去验证题目中给出的序列即可,我用代码详细讲。

两个数学公式:

1:a1=(sn-n*(n-1)/2*d)/n

2:Sn^2=n(a1)^2+n(n-1)(2n-1)d^2/6+n(n-1)*d*a1

膜一发我的Q。

代码:

//a1=(sn-n*(n-1)/2*d)/n
//Sn^2=n(a1)^2+n(n-1)(2n-1)d^2/6+n(n-1)*d*a1  两个数学公式的运用
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int a[300000];//存放输入取模后的序列
int s[2];//两个数学公式的结果
int b[300000];//存放验证取模后的序列
int fp(int a,int k,int m){//费马小定理+快速幂求逆元
int res=1;
while(k){
if(k&1) res=1LL*res*a%m;
a=1LL*a*a%m;
k>>=1;
}
return res;
}
int main(){
int m,n;
scanf("%d%d",&m,&n);
s[0]=s[1]=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[0]=(s[0]+a[i])%m;
s[1]=(s[1]+1LL*a[i]*a[i])%m;
}
if(n==1){//特殊情况
return 0*printf("%d 0\n",a[1]);
}
    sort(a+1,a+n+1);
for(int i=2;i<=n;i++){
int d=(a[i]-a[1]+m)%m;//枚举每一个d,这里可以仔细想一下,意思其实就是肯定会有一个和a[1]在原序列中相邻的1个数,那么两者做差就是d
int x=1LL*(s[0]-1LL*n*(n-1)/2%m*d%m+m)%m*fp(n,m-2,m)%m;//枚举每一个a1
int ans=1LL*n*x%m*x%m;//第二个式子求和
ans=(ans+1LL*n*(n-1)%m*d%m*x%m)%m;
ans=(ans+1LL*n*(n-1)*(2*n-1)/6%m*d%m*d%m)%m;
if(ans==s[1]){//当Sn^2相等时,验证
b[1]=x;
for(int j=2;j<=n;j++){//构造自己取模后的序列
b[j]=b[j-1]+d;
b[j]%=m;
}
sort(b+1,b+n+1);
bool flag=true;
for(int j=1;j<=n;j++){//验证
if(a[j]!=b[j]){
flag=false;
break;
}
}
if(flag){//输出
return 0*printf("%d %d\n",x,d);
}
}
}
return 0*printf("-1\n");
}


跟着Q神又学了点东西,再次膜。




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: