Given sequence ss of length nn and sequence tt of length mm, find the length of the longest common subsequence of ssand tt.
There are multiple test cases. The first line of input contains an integer TT(1≤T≤1031≤T≤103), the number of test cases. For each test case: The only line contains 77 integers, nn, mm, pp, xx, aa, bb, cc (1≤n1≤n, m≤106m≤106, 0≤x0≤x, aa, bb, c
For each test case: Output an integer -- the length of the longest common subsequence of ss and tt, in one line.
示例1
2 4 3 1024 1 1 1 1 3 4 1024 0 0 0 0
0 3
In the first sample, s=[3,13,183,905]s=[3,13,183,905] and t=[731,565,303]t=[731,565,303]. In the second sample, s=[0,0,0]s=[0,0,0] and t=[0,0,0,0]t=[0,0,0,0].
题意: 给出一个长度为n的数组以及一个长度为m的数组,求它们的最长公共子序列,数组中的值按照一定规则生成,给出x、a、b和c,令x = a*x^2 + b*x + c,然后把x填入数组中第i个位置,如此往复直至遍历完数组。
分析: 由于n和m都是1e6级别的,所以没法直接跑n^2的lcs算法,可以注意到两个数组中数据生成都是有规律的,第i+1个位置的值是通过第i个位置的值得到的,如果一旦出现a[i]等于b[j],那么a数组第i个位置和b数组第j个位置后面的值一定是相同的,所以问题就很好解决了,只需要记录下a数组中a[i]首次出现的位置,然后遍历b数组,当b[i]在a数组中出现过时,就可以更新一次答案,最终结果取最大值。
具体代码如下:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
-
- unordered_map<int, int> mp;
-
- signed main()
- {
- int T;
- cin >> T;
- while(T--){
- mp.clear();
- int n, m, p, x, a, b, c;
- scanf("%d%d%d%d%d%d%d", &n, &m, &p, &x, &a, &b, &c);
- for(int i = 1; i <= n; i++){
- x = ((1ll*a*x%p*x%p+1ll*b*x%p)%p+c)%p;
- if(!mp.count(x))
- mp[x] = i;
- }
- int ans = 0;
- for(int i = 1; i <= m; i++){
- x = ((1ll*a*x%p*x%p+1ll*b*x%p)%p+c)%p;
- if(mp[x]) ans = max(ans, min(n-mp[x]+1, m-i+1));
- }
- printf("%d\n", ans);
- }
- return 0;
- }