链接
题目描述
有一个长为n*k的数组,它是由长为n的数组 重复 k 次得到的。
定义这个数组的一个区间的权值为它里面不同的数的个数,现在,你需要求出对于这个数组的每个非空区间的权值之和。
思路
一个数a出现的次数 = 总区间个数 - 不出现a的区间个数
那么就可以考虑求不出现a的区间个数
两个a之间的区间不包含a,所以就求这些区间就好了
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
vector<int> g[100005];
ll n, m, res, k, inv;
const ll mo = 1e9 + 7;
ll ans, v[100005], p[100005];
ll ksm(ll a, ll b, ll p)
{
ll re = 1;
while(b)
{
if(b & 1) re = re * a % p;
a = a * a % p;
b >>= 1;
}
return re % p;
}
ll read()
{
ll x = 0, flag = 1; char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') flag = -1; ch = getchar();}
while (ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0'; ch = getchar();}
return x * flag;
}
int work(int len)
{
return 1ll * (len + 1) % mo * (len + 2) % mo * inv % mo;
}
int main()
{
freopen("loop.in", "r", stdin);
freopen("loop.out", "w", stdout);
n = read(); k = read();
for(int i = 1; i <= n; ++i)
v[i] = read(), p[i] = v[i];
sort(p + 1, p + n + 1);
int tot = unique(p + 1, p + n + 1) - p - 1;
for (int j = 1; j <= n; ++j)
v[j] = lower_bound(p + 1, p + tot + 1, v[j]) - p,
g[v[j]].push_back(j);
inv = ksm(2, mo - 2, mo);
for(int i = 1; i <= tot; ++i)
{
int siz = g[i].size();
res = 0;
for(int j = 1; j < siz; ++j)
{
int x = g[i][j - 1] + 1, y = g[i][j] - 1;
res = (res + 1ll * work(y - x) % mo * k % mo) % mo;
}
int x = g[i][siz - 1], y = g[i][0];
res = (1ll * res + work(y - 2) % mo) % mo;
res = (1ll * res + work(n - x - 1) % mo) % mo;
res = (1ll * res + 1ll * work(y + n - 1 - (x + 1)) % mo * (k - 1) % mo) % mo;
int Ans = ((work((1ll * n * k - 1) % mo) % mo - res) % mo + mo) % mo;
ans = (Ans + ans) % mo;
}
printf("%lld", ans);
return 0;
}