Cf #709 Div. 2 B. Restore Modulo 一个只有三千多人过的b题, 妙啊!

传送门: https://codeforces.com/contest/1484/problem/B

原题

 

Example
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
output
19 8
-1
-1
-1
2000000000 1000000000
0

题意

(前言: 这次唯一没有遗憾的怕就是没有英语bug了, 2个小时, b题依然没过, 思路大致对, 但是但是, 代码写出来写好最关键!)

给一个数组, 有n个数字, 其中a1=s%m, ai=(ai-1+c)%m    (这里描述的下标是从1~n, 其中0<=c<m)

目标:输出以下符合的条件一点

   1. 找出m, c并输出; 

  2.m可无限大时, 输出0

  3.没有匹配的m, c时, 输出-1

 

 


 

 

思路

总体来看:

c还是好想的, (虽然刚开始毫无思路, 这时候上手就行了, 划拉划拉就有思路了)

对c来说: 只要ai-1 < ai , 因为c<m, 加上的数不会大于取模的值, 这次没有用到取余ai-1 + c = ai, 那c = ai - ai-1

求到了c后, m也好找了, 只要ai-1 > a, 那么这次肯定用到取余了, (ai-1 + c) % m = ai , 其中商一定为1, 那么变形得到m = ai-1 - ai + c

逐个击破, 先看特殊情况:

(一) m可无限大:  数列单调而且为等差数列, ai - ai-1 == 0也行

(二) 没有匹配的值时, 两种情况: 

              1. m, c无法求.   -----> 缺少ai-1 < a或 ai-1 > ai,

              2. m, c求后不符合条件.   -----> m小于数列最大值或增减两情况下ai - ai-1有多组答案, 即size>1(0<=c<m一定满足, 因为m = c + 一个正数)

 


收获

明白了这些我的代码写的依然很乱, 第一次体验代码能力的重要性. 

当时专门写了两个循环来看m, c, 其中还有个循环, 每次都用了max()函数, 

事后看了大佬的代码后, 发现一个set函数就直接解决了(二).1, 分别求出了递增和递减的, 而且Set函数自带去重

每次都用max函数, 复杂度会偏高, 不如最后一次用sort, 二分排序, 快得很

代码

#include <iostream>
#include <set>
#include <algorithm>
using namespace std; const int N=1e5+10; int a[N]; int main() { int t; cin >> t; while(t--) { int n; cin >> n; set<int> fir, sec; for(int i = 0;i <n;i ++) { cin >> a[i]; if(i) if(a[i] < a[i-1])//c可以为 0 fir.insert(a[i]-a[i-1]); else sec.insert(a[i]-a[i-1]); } if(fir.size() > 1 || sec.size() > 1) puts("-1"); else if(fir.size() == 0 || sec.size() == 0) puts("0"); else { int c = *sec.begin(); int m = c - *fir.begin(); sort(a, a+n); if(m <= a[n-1]) puts("-1"); else printf("%d %d ", m, c); } } return 0; }


作者:la-la-wanf
链接:https://www.cnblogs.com/la-la-wanf/p/14566941.html
来源:博客园
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文地址:https://www.cnblogs.com/la-la-wanf/p/14566941.html