快手笔试,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转化为求的最长上升子序列,其中
f_i两个可选值。
而最长上升子序列是可以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;
}



#快手笔试##快手##笔试题目#
全部评论
你的数组生成跟我的找LCS拼起来就是全对了哈哈哈  我是使用vector<int>内存爆了
点赞 回复 分享
发布于 2020-03-22 22:04
似乎知道为什么了…… 应该返回max(max(dp[i][0], dp[i][1])) \forall i ...... 大概是写代码的时候头脑发热了罢😓
点赞 回复 分享
发布于 2020-03-22 21:57

相关推荐

05-07 20:52
吉林大学 Java
点赞 评论 收藏
分享
高斯林的信徒:武大简历挂?我勒个骚岗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务