Description
Input
Output
Sample Input
Sample Input1
4 3
1 2 1 0
Sample Input2
11 8
1 2 3 4 5 0 5 4 3 2 1
Sample Input3
20 100
30 91 15 72 61 41 10 37 98 41 94 80 26 96 10 88 59 5 84 14
Sample Output
Sample Output1
2
Sample Output2
8
Sample Output3
313
Data Constraint
Solution
DAY1第二题,考场上就只打了暴力。。
这题正解是差分,先将原密码前后都补个0,做差分,共有
n+1 个差分数。设差分数组为
f] ,即得到f[i]=a[i+1]−a[i] ,注意这里是在模m 意义下。那么进行一次操作就相当于在差分数组上两个位置加减。
接着我们考虑贪心地填,将差分数组从小到大排序。那么小的就减到
0 ,大的就加到m 。计算
f[i] 前缀和,m−f[i] 后缀和,枚举分割位置,前后缀相等的位置即为答案。
Code
#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;
const int N=1e6+5;
int a[N],f[N];
long long pre[N],suf[N];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
int main()
{
freopen("lock.in","r",stdin);
freopen("lock.out","w",stdout);
int n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n+1;i++) f[i]=((long long)a[i]-a[i-1]+m)%m;
sort(f+1,f+1+n+1);
for(int i=1;i<=n+1;i++) pre[i]=pre[i-1]+f[i];
for(int i=n+1;i;i--)
{
suf[i]=suf[i+1]+m-f[i];
if(suf[i]==pre[i-1]) return 0&printf("%lld",suf[i]);
}
}