快手笔试,A卷第三题,这个思路哪里出了问题?
刚结束的快手笔试,前两道题特别简单,后两道题特别难=-=
第四题是一道计算几何,微积分好久不摸了,勉强用暴力骗到20分;
第三题:
给定0 < S, A, B, P < 200000,以如下方式生成序列:
1)arr[0] = S, i = 1
2)x = (arr[i-1]*A+B)%P,
3)若x已在arr[0]~arr[i-1]中出现两次则终止,否则i=i+1, arr[i] = x,转1
现在给出两组S A B P,求生成的两个序列的最长公共子序列的长度
——————————————————————————————
记第一序列为a[],第二序列为b[]。
序列的长度最长为399998,显然不能直接求LCS。由于序列的每个元素都在[0, P)中,且最多出现两次,故考虑对于每个
记录它在第二序列中出现的位置pos[i][0]和pos[i][1]。对于出现不足两次的情况,用-1标记。(即,若只出现一次,则pos[i][1] = -1,若不出现,则pos[i][0] = pos[i][1] = -1)
由于最长公共子序列的各个元素在原序列中的下标都是递增的,那么可以把a[]和b[]的LCS转化为求
的最长上升子序列,其中
而最长上升子序列是可以O(nlogn)求的,不会超时:
同理求得dp[i][1]
———————————————————————————————
但是,利用这个思路写出来的代码并没有通过,通过率0%。问题出在了哪里?请各位大佬赐教QwQ
#include <iostream>
#include <cstring>
typedef long long LL;
const int MAXP = 2e5+5;
int a[MAXP*3], b[MAXP*3], dp[MAXP][2];
int found[MAXP][2];
int min_b[MAXP*3];
using namespace std;
void Generate(int S, int A, int B, int P, char arr_mark, int &n){
int *arr = (arr_mark == 'a' ? a : b);
int vis[MAXP];
memset(vis, 0, sizeof(vis));
if(arr_mark == 'b'){
memset(found, -1, sizeof(found));
}
arr[0] = S;
if(arr_mark == 'b'){
found[S][0] = 0;
}
vis[S] = 1;
n = 1;
for(;; n++){
int tmp = int((LL(arr[n-1])*A+B)%P);
if(vis[tmp] == 2)break;
if(arr_mark == 'b'){
found[tmp][vis[tmp]] = n;
}
vis[tmp] ++;
arr[n] = tmp;
}
}
int BSearch(int l, int r, int k, int* arr){
while (l < r){
int mid = (l+r)/2;
if(arr[mid] >= k) r = mid;
else l = mid+1;
}
//cout << l << endl;
return l-1;
}
int main(){
int T,S,A,B,P,Sb,Ab,Bb,Pb, na, nb;
cin >> T;
while(T--){
na = 0;
nb = 0;
cin >> S >> A >> B >> P;
Generate(S, A, B, P, 'a', na);
cin >> S >> A >> B >> P;
Generate(S, A, B, P, 'b', nb);
//for(int i = 0; i < na; i++)cout << a[i] << ' ';
//cout << endl;
//for(int i = 0; i < nb; i++)cout << b[i] << ' ';
//cout << endl;
memset(dp, 0, sizeof(dp));
memset(min_b, 0x3f, sizeof(min_b));
min_b[0] = -1;
for(int i = 0; i < na; i++){
int fd0 = found[a[i]][0];
int fd1 = found[a[i]][1];
//cout << "I = " << i << " FD0 = " << fd0 << " FD1 = " << fd1 <<endl;
dp[i][0] = dp[i][1] = 0;
if(fd0 != -1){
dp[i][0] = 1;
min_b[1] = min(min_b[1], fd0);
}
if(fd1 != -1){
dp[i][1] = 1;
min_b[1] = min(min_b[1], fd1);
}
if(i > 0){
if(fd0 != -1){
int idx = BSearch(0, 3*MAXP-1, fd0, min_b);
dp[i][0] = idx+1;
min_b[dp[i][0]] = min(min_b[dp[i][0]], fd0);
}
if(fd1 != -1){
int idx = BSearch(0, 3*MAXP-1, fd1, min_b);
dp[i][1] = idx+1;
min_b[dp[i][1]] = min(min_b[dp[i][1]], fd1);
}
}
//cout << "I = " << i << " dp0 = " << dp[i][0] << " dp1 = " << dp[i][1] <<endl;
}
cout << max(dp[na-1][0], dp[na-1][1]) <<endl;
}
return 0;
}
