基准时间限制:0.7 秒 空间限制:131072 KB 分值: 80
难度:5级算法题
阿尔法在玩一个游戏,阿尔法给出了一个长度为n的序列,他认为,一段好的区间,它的长度是>=k的,且该区间的第k大的那个数,一定大于等于T。那么问题来了,阿尔法想知道有多少好的区间。
由于阿尔法的序列长度实在是太大了,无法在规定时间内读入。
他想了一个绝妙的方法。
读入a[0],b,c,p,则a[i]=(a[i-1]*b+c)mod p。
样例解释:
a1~a5分别为47,135,247,35,147
对应的7个区间分别为[1,3],[2,3],[1,4],[2,4],[1,5],[2,5],[3,5]
对于重复的数字1,2,2 第一大是2,第二大也是2,第三大是1。
Input
读入一行,7个数字,表示n(n<=10000000),k(k<=n),T,a[0],b,c,p。 所有数字均为正整数且小于等于10^9。
Output
输出一行表示好区间的个数。
Input示例
5 2 100 10 124 7 300
Output示例
7
官方题解:
对于一个数,我们只需要知道它与T的相对大小关系,因此题目可以转化为求存在多少区间大于等于k。
假如固定左端点,那么对于一个好区间,那么右端点一定是连续的,若左端点向右移动,那么最近右端点不可能向左移动。因此可以使用双指针来做这题。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <windows.h>
#include <cstring>
#include <cstring>
#include <vector>
#include <string>
#include <time.h>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3fffffff
const int maxn = 10000005;
ll n, k, T, a0, b, c, p;
int che[maxn];
ll val[maxn];
void input()
{
scanf("%lld%lld%lld%lld%lld%lld%lld", &n, &k, &T, &a0, &b, &c, &p);
}
void solve()
{
int i, kk = 0;
val[1] = (a0*b + c) % p;
if (val[1] >= T)
{
che[1] = 1;
}
for (i = 2; i <= n; i++)
{
val[i] = (val[i - 1] * b + c) % p;
if (val[i] >= T)
{
che[i] = 1;
}
}
ll res = 0;
int lef = 1, rig = 1;
while (rig <= n)
{
if (che[rig])
{
kk++;
}
if (kk == k)
{
break;
}
rig++;
}
while (rig <= n&&rig - lef + 1 >= k)
{
res += (n - rig + 1);
if (che[lef])
{
while (rig <= n)
{
rig++;
if (che[rig])
{
break;
}
}
}
lef++;
}
cout << res;
}
int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
input();
solve();
//system("pause");
return 0;
}