CF289B题解
:
首先可以发现一个性质:
意思是说,一个数加上 ,这个数除以 得到的余数不变。
由此我们可以想到,要想使数组 每个元素相等,他们模 得到的值一定要是一样的。
暴力的话要 ,太慢了,所以可以进行一点优化:
因为只要有两个不同的数,就可以输出 -1,所以我们记录
当然,还有更快的 的写法:
//这里,b[i][j]表示a[i][j]%d
int l=-1;
bool F=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(l==-1) l=b[i][j];
else if(b[i][j]!=l){
F=1;
break;
}
}
if(F) break;
}
if(F) return !printf("-1");
接下来就是求答案了。
不难想到,要想操作次数最小,最后要变成在 数组升序(或降序)排序最中间(偶数个的话有两个)。
只要将 数组保存在一个一维数组里,排序一下(升序或降序都可以),对于每个值,求出它到中间值要几步,相加即可。
//这里,c[1~t]包含了a数组的全部元素,t=n*m
if(F) return !printf("-1");
sort(c+1,c+t+1,cmp);
for(int i=1;i<=t;i++){
ans+=abs(c[(1+t)>>1]-c[i])/d;
}
printf("%d",ans);
完整代码
#include<bits/stdc++.h>
using namespace std;
int n,m,a[110][110],d,b[110][110],c[10010],t,ans;
bool cmp(int x,int y){
return x<y;
}
int main(){
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
b[i][j]=a[i][j]%d;
c[++t]=a[i][j];
}
}
bool F=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int u=1;u<=n;u++){
for(int v=1;v<=m;v++){
if(b[i][j]!=b[u][v]){
F=1;
break;
}
}
if(F) break;
}
if(F) break;
}
if(F) break;
}
if(F) return !printf("-1");
sort(c+1,c+t+1,cmp);
for(int i=1;i<=t;i++){
ans+=abs(c[(1+t)>>1]-c[i])/d;
}
printf("%d",ans);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,a[110][110],d,b[110][110],c[10010],t,ans;
bool cmp(int x,int y){
return x<y;
}
int main(){
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
b[i][j]=a[i][j]%d;
c[++t]=a[i][j];
}
}
int l=-1;
bool F=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(l==-1) l=b[i][j];
else if(b[i][j]!=l){
F=1;
break;
}
}
if(F) break;
}
if(F) return !printf("-1");
sort(c+1,c+t+1,cmp);
for(int i=1;i<=t;i++){
ans+=abs(c[(1+t)>>1]-c[i])/d;
}
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号