[CodeForces-763C]Timofey and remoduling
题目大意:
告诉你一个长度为n的等差数列在模m意义下的乱序值(互不相等),问是否真的存在满足条件的等差数列,并尝试构造任意一个这样的数列。
思路:
首先我们可以有一个结论:
两个等差数列相等,当且仅当数字和与平方和分别相等。
首先求出一开始的数字和和平方和。
然后我们枚举每一个数作为首项的情况,求出这个数作为首项以后的数字和和平方和,根据数字和求出公差,然后用平方和检验一下。
然而这样并不能保证一定正确,但至少有大概率是正确的,我们可以O(n)的时间检验一下。
注意特判n=m的情况。
1 #include<cstdio> 2 #include<hash_set> 3 typedef long long int64; 4 inline int getint() { 5 register char ch; 6 while(!__builtin_isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(__builtin_isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 __gnu_cxx::hash_set<int> set; 12 const int64 N=100000; 13 int64 a[N]; 14 int64 m,n; 15 inline int64 sqr(const int64 &x) { 16 return x*x%m; 17 } 18 void exgcd(const int64 &a,const int64 &b,int64 &x,int64 &y) { 19 if(!b) { 20 x=1; 21 y=0; 22 return; 23 } 24 exgcd(b,a%b,y,x); 25 y-=a/b*x; 26 } 27 inline int64 inv(const int64 &x) { 28 int64 tmp,ret; 29 exgcd(x,m,ret,tmp); 30 return (ret+m)%m; 31 } 32 int main() { 33 m=getint(),n=getint(); 34 if(n==m) { 35 __builtin_puts("0 1"); 36 return 0; 37 } 38 int64 sum0=0,sqrsum0=0; 39 for(register int64 i=0;i<n;i++) { 40 a[i]=getint(); 41 set.insert(a[i]); 42 sum0=(sum0+a[i])%m; 43 sqrsum0=(sqrsum0+sqr(a[i]))%m; 44 } 45 const int64 c=inv(n*(n-1)/2); 46 for(register int64 i=0;i<n;i++) { 47 const int64 sum=((sum0-a[i]*n%m)%m+m)%m; 48 const int64 sqrsum=((sqrsum0-sqr(a[i])*n%m-a[i]*sum%m*2%m)%m+m)%m; 49 const int64 d=sum*c%m; 50 if(n*(n-1)*(n*2-1)/6%m*sqr(d)%m!=sqrsum) continue; 51 int64 tmp=a[i]; 52 for(register int64 i=1;i<n;i++) { 53 tmp=(tmp+d)%m; 54 if(!set.count(tmp)) goto Next; 55 } 56 __builtin_printf("%I64d %I64d\n",a[i],d); 57 return 0; 58 Next:; 59 } 60 __builtin_puts("-1"); 61 return 0; 62 }