T1
当然不能枚举每个区间,于是我们考虑算贡献。
对于每个位置i,我们计算其作为区间内第一个出现ai的位置的区间总数,则有ans=sigma( i - last[i] ) * ( n - i + 1 ) ,n为区间长度,last[i]为上一个出现ai的位置。
(其实还有一种简单的递推思路,定义f[i]为前 i 个数的权值和,f[i] = fi[-1] + i - last[i] ,可是我太菜了,没想清楚以为是错的Orz)
这样我们解决了k=1的情况。
然后我们考虑k不等于1
如果我们复制第一段区间插在后面,定义第一段区间的权值和为C1,前两段为C2,则第二段对这两段的贡献delta=C2-C1,而且显然 第三段对第二、三两段的贡献也为delta,后面的同理。
这样我们解决了相邻复读区间的贡献。
对于不相邻的复读区间,由于跨一整个区间,则每个区间的权值都为tot,计算这些区间的总数即可。
代码:
#include <cstdio>
#include <map>
#include <iostream>
#define int long long int
using namespace std;
const int mod=1e9+7;
inline int read() {
int x=0,f=1;
char cr=getchar();
while (cr>'9' || cr<'0') {
if (cr=='-') f=-1;
cr=getchar();
}
while (cr>='0' && cr<='9') {
x=(x<<3)+(x<<1)+cr-'0';
cr=getchar();
}
return x*f;
}
const int maxn=1000500;
map<int,int> loc;
int a[maxn],last[maxn];
inline int sigma(int k) {
int x=k,y=k+1;
if (x&1) return (y/2*x)%mod;
return (x/2*y)%mod;
}
signed main() {
int n=read(),k=read();
int tot=0;
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++) {
if (!loc[a[i]]) tot++;
last[i]=loc[a[i]],loc[a[i]]=i;
}
if (k==1) {
int ans=0;
for (int i=1;i<=n;i++) ans+=(i-last[i])*(n-i+1),ans%=mod;
printf("%lld",ans);
return 0;
}
else {
int cont1=0,cont2=0;
for (int i=1;i<=n;i++) cont1+=(i-last[i])*(n-i+1),cont1%=mod;
for (int i=n+1;i<=2*n;i++) a[i]=a[i-n],last[i]=loc[a[i]],loc[a[i]]=i;
for (int i=1;i<=2*n;i++) cont2+=(i-last[i])*(2*n-i+1),cont2%=mod;
int delt=cont2-cont1+mod;delt%=mod;
int ans=cont2;
ans+=(k-2)*(delt),ans%=mod;
ans+=(sigma(k-2)*n%mod*n%mod*tot%mod)%mod,ans%=mod;
printf("%lld",ans);
return 0;
}
}