Description
上了大学之后,小W和小Z一起报了一门水课,在做作业时遇到了问题。有一个长度为 n 的数列{ai},为一列树木的美观值。现在有m 次询问,每次给出三个数l,r和P,询问对于所有的l <= l’ <= r’ <= r (a[l’] + a[l’ + 1] + … + a[r’]) mod P的最小值。
Data Constraint
对于20%的数据
1 <= n, m <= 1000,1 <= l <= r <= n, 1 <= P <= 100,0 <= a[i] <= 10^9
对于另外的30%的数据
1 <= n, m <= 50000,1 <= l <= r <= n, 1 <= P <= 10,0 <= a[i] <= 10^9
对于100%的数据
1 <= n, m <= 50000, 1 <= l <= r <= n, 1 <= P <= 100, 0 <= a[i] <= 10^9
Solution
我们设1~i的前缀和为s[i],那么对于一个点l’,r’,他们的答案显然是(s[r’]-s[l’])%P。假设我们固定l’,假设两个r1’,r’的(s[r’]-s[l’])%P相同,那么显然(s[r1’]-s[r’])%P=0。所以我们可以断定,除非(s[r’]-s[l’])%P两两不相同,否则答案一定为零。那么,现在对于一个询问l,r,假设他们之间的距离大于P,那么显然一定会出现(s[r’]-s[l’])%P相同的情况,所以我们直接输出答案0即可,否则暴力跑一下就好了
Code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int mo=100,maxn=50005;
struct code{
int a,l,r,b;
}b[maxn];
int n,m,i,t,j,k,l,num,p,r,mi,x,y,yy;
ll s[maxn],a[maxn],ans[maxn];
bool bz[mo];
bool cmp(code x,code y){
return x.a<y.a || x.a==y.a && x.r<y.r;
}
int main(){
freopen("garden.in","r",stdin);freopen("garden.out","w",stdout);
// freopen("data.in","r",stdin);
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
for (i=1;i<=m;i++)
scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].a),b[i].b=i;
sort(b+1,b+m+1,cmp);
for (i=1;i<=m;i++){
p=b[i].a;l=b[i].l;r=b[i].r;
mi=1e9;bz[0]=true;
if (r-l+1<=p){
for (j=l;j<=r;j++){
t=0;
for (k=j;k<=r;k++){
t=(t+a[k])%p;
mi=min(mi,t);
}
}
ans[b[i].b]=mi;
}
}
for (i=1;i<=m;i++)
printf("%d\n",ans[i]);
}