正题
题目链接:https://ac.nowcoder.com/acm/contest/1103/A
题目大意
将一个长度为nnn的数组复制成kkk份,然后每个区间的值是一个区间中不同的数的数量,求每个非空区间的值和。
解题思路
若一个区间长度>n>n>n那么他们的值是固定的,所以我们可以先计算出这些区间的答案。
现在只需要考虑长度<n<n<n的区间,我们讲原数组复制一份放到后面后,我们用fif_ifi表示第iii个结尾的区间权值和。若不考虑iii这个位置的贡献那么fi=fi−1f_i=f_{i-1}fi=fi−1,iii这个位置影响的区间是到上一个和它相同的位置lastlastlast。也就是fi=fi−1+i−lastf_i=f_{i-1}+i-lastfi=fi−1+i−last。
当i>ni>ni>n时我们不能计算左端点>n>n>n的区间,所以我们就改为fi=fi−1+max{n−last,0}f_i=f_{i-1}+max\{n-last,0\}fi=fi−1+max{n−last,0}即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,XJQ=1e9+7;
ll n,k,a[N],ans,num,b[N],v[N];
ll power(ll x,ll b)
{ll ans=1;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
int main()
{scanf("%lld%lld",&n,&k);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i];sort(b+1,b+1+n);ll cnt=unique(b+1,b+1+n)-b-1;for(ll i=1;i<=n;i++){a[i]=a[i+n]=lower_bound(b+1,b+1+cnt,a[i])-b;if(!v[a[i]]) v[a[i]]=i,num++;}ans=num*n%XJQ*n%XJQ;ans=ans*max((k-2)*(k-1)%XJQ,0ll)%XJQ*power(2,XJQ-2)%XJQ;memset(v,0,sizeof(v));num=0;ll sum=0,z=0;for(ll i=1;i<=2*n;i++){ll last=0;if(v[a[i]]) last=v[a[i]];v[a[i]]=i;if(i>n) z+=max(n-last,0ll);else z+=i-last-(i>n);(sum+=z*(k-(i>n))%XJQ)%=XJQ;}printf("%lld",(ans+sum)%XJQ);
}