F题 Longest Common Subsequence
用 x(i1)=(a*xi^2+b*xi+c)mod p构造一个长为2n的序列,序列前n个数字记为a ,后n个数字记为 b。求a和b的最长公共子序列。
当xi=xj时,则f(xi)=f(xj)。所以记录每一次x最先出现的位置, ans=max(ans,min(n−i+1,m−j+1))
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const int mod=998244353;
const int N=1e6+10,M=1e6+5;
ll n,m,p,x,a,b,c;
int A[N],B[N];
vector<int> nums;
int lis(vector<int>& nums) {
if(nums.size()<2) return nums.size();
vector<int> seq{nums[0]};
for(int i=1; i<nums.size(); i++)
{
int idx = lower_bound(seq.begin(), seq.end(), nums[i])-seq.begin();
if(idx==seq.size()) seq.push_back(nums[i]);
else seq[idx]=nums[i];
}
return seq.size();
}
int lcs1() {
unordered_map<int, vector<int>> has; // 统计字符出现的下标
for(int i=m; i>=1; i--) has[B[i]].push_back(i);
nums.clear();
for(int i=1; i<=n; i++)
for(int j=0; j<has[A[i]].size(); j++) nums.push_back(has[A[i]][j]);
// for(int i=0;i<seq.size();i++) cout<<seq[i]<<endl;
return lis(nums); // 求seq的最长上升子序列即是答案
}
int get(ll x) {
return (a*x%p*x%p+b*x%p+c)%p;
}
void solve() {
cin>>n>>m>>p>>x>>a>>b>>c;
for(int i=1;i<=n;i++) {
x = get(x); A[i]=x;
//cin>>A[i];
}
for(int i=1;i<=m;i++) {
x=get(x); B[i]=x;
//cin>>B[i];
}
int ans=lcs1();
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int T=1; cin>>T;
while(T--) {
solve();
}
return 0;
}