问题描述:
给定一个数字序列{X1, X2, ... , Xn}, 假定 Xk = (A * k + B) % mod。你的任务就是找一个最大的子序列{Y1, Y2, ... , Ym} ,对于每对 (Yi, Yj)要求满足Yi + Yj <= L (1 ≤ i < j ≤ m), 而且同时满足Yi <= L (1 ≤ i ≤ m )。
现在给定n,L,A,B和mod,你的任务就是找出上述最大的m值。
输入:
输入包括多组测试数据,直到文件尾。每个测试数据占一行,包括5个整数: n, L, A, B 和mod. (1 ≤ n ≤ 2*10^7, 1 ≤ L ≤ 2*10^9, 1 ≤ A, B, mod ≤ 109)(变量用long long类型)
输出:
对于每组测试数据,输出m值,占一行。
输入样例:
1 8 2 3 6
5 8 2 3 6
输出样例:
1
4
解题分析:
注意Xk = (A * k + B) % mod,x的取值只与k有关,第一个x取值就与1有关,第2个x取值就与2有关,所以先利用给出的n算出x序列。
题目中要求从x序列中抽出m个数字组成y序列,即y序列是x序列的子序列,且y序列中的每两个任意数字(不能是本身)相加之和都小于l,所以针对x序列中的每一个数字进行运算判断即可,如果满足条件则m++,下面来看满足条件的情况。
先设置max与min变量,令max=0,min=l.(注意max变量存储的是小于l/2的最大值,min变量存储的是大于l/2的最小值)
如果x<=l/2,那么m++(也就是如果y序列里只有x这一个数字,它又小于l/2,肯定满足题中情况),且如果x>max,则令x=max;如果x>l/2,且如果x<min,则令x=min。即,记录下小于l/2的最大值与大于l<2的最小值,如果max+min≤l,则m++。
需要注意的是,m是y序列中数字的个数,而非数组下标数。
#include <stdio.h>
#include <string.h>
int main()
{
long long n,l,a,b,mod;
while(scanf("%lld %lld %lld %lld %lld",&n,&l,&a,&b,&mod)!=EOF){
long long i,x,max=l,min=0,m=0;
for(i=1;i<=n;i++){
x=(a*i+b)%mod;
if(x<=l/2){
m++;
if(x>min) min=x;
}
else if(x<max) max=x;
}
if(min+max<=l) m++;
printf("%lld\n",m);
}
return 0;
}