題意
定義\(F_i\)為斐波那契數列第\(i\)項,\(F_1=1,\ F_2=2,\ F_i=F_{i-1}+F_{i-2}\ (i≥3)\)
已知任意正整數\(x\)都擁有一個唯一的長度為\(n\)的\(01\)數列\(\{b\}\),使得
\(b_1*F_1+b_2*F_2+...+b_n*F_n=x\)
\(b_n=1\)
\(b_i∈\{0,1\}\)
\(b_i*b_{i+1}=0\)
以這樣的表示法給出\(A、B、C\)三個數
已知數字\(C\)是由\(A*B\)的結果在這樣的表示法下將某個原本是\(1\)的位置改成\(0\)得來的
問抹去的是哪個位置
數據范圍
\(1≤T≤10000\)
\(1≤|A|,|B|≤1000000\)
\(2≤|C|≤|A|+|B|+1\)
\(\sum|A|,\sum|B|≤5000000\)
解
根據數據范圍,至少要預處理出前\(2000001\)項的斐波那契數列
並通過\(map/unordered\_map/gp\_hash\_table\)將值映射回位置
然后根據題目所述,計算出\(A\)、\(B\)和\(C\)的值
其次只要通過\(A*B-C\)來計算出被抹去的數對應的數字是什么,將映射的位置輸出即可
想法理解了之后就只剩處理方法的問題了
首先發現\(Fibonacci\)數列前\(100\)項便會超出\(long\ long\)的范圍,所以需要對其進行取模
我們需要保證這個模數能讓\(Fibonacci\)數列前\(2000001\)項在取模后沒有沖突(唯一性)
所以需要一個比平時見到的模數更大的模數去嘗試(類似\(998244353、1000000007\)這些均有沖突項數)
最后我取了\(1111111111139\)這個模數(若使用\(unsigned\ long\ long\)可以使用哈希的想法讓數自然溢出,應該也是對的)
於是就能預處理+映射求出答案了,詳見代碼
需要注意的是,模數過大可能會導致計算\(A*B\)時超出\(long\ long\)的范圍,所以需要使用快速乘
完整程序(各種優化情況)
由於組數關系及數據范圍,所以我們需要考慮應當選取怎樣的容器去映射
經(不完全)測試,得到結果如下
容器/讀入方式 | 賽時測評(ms) | 題庫測評(ms) |
---|---|---|
map + STDIO | / | TLE |
unordered_map + STDIO | 2453 | / |
gp_hash_table + STDIO | 2015 | / |
unordered_map + FastIO | / | 2698 |
gp_hash_table + FastIO | 375 | 1107 |
數據過大,快讀這題在題庫測評時應該是少不了的
其次稍微提一下,如果提交的是\(G++\),且需要使用\(unordered\_map\)類時
如果空間充足,建議使用\(gp\_hash\_table\)來代替,時間復雜度可以降低\(2\)$3$倍,但空間復雜度會提高$1.5$\(2\)倍
在實際使用過程中,除了\(gp\_hash\_table\)無法使用\(count\)函數外,其余與\(unordered\_map\)相同
使用方法如下(兩個頭文件&一個namespace,添加后就能使用了)
下面展示的是\(gp\_hash\_table + FastIO\)組合的程序
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
const int bsz=1<<18;
char bf[bsz],*head,*tail;
inline char gc(){
if(head==tail){
int l=fread(bf,1,bsz,stdin);
tail=(head=bf)+l;
}
return *head++;
}
inline int read(){
int x=0,f=1;
char c=gc();
for(;!isdigit(c);c=gc())
if(c=='-')
f=-1;
for(;isdigit(c);c=gc())
x=x*10+c-'0';
return x*f;
}
inline void write(ll x){
if(x>=10)
write(x/10);
putchar(x%10+'0');
}
inline void putd(ll x)
{
write(x);
putchar('\n');
}
const ll mod=1111111111139LL;
gp_hash_table<ll,int> mp;
ll fibo[2000050];
ll qmul(ll a,ll b){ //快速乘
ll r=0;
while(b){
if(b&1)
r=(r+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return r;
}
void solve()
{
int cnt1,cnt2,cnt3,d;
ll A=0,B=0,C=0;
cnt1=read();
for(int i=1;i<=cnt1;i++)
{
d=read();
if(d==1)
A=(A+fibo[i])%mod;
}
cnt2=read();
for(int i=1;i<=cnt2;i++)
{
d=read();
if(d==1)
B=(B+fibo[i])%mod;
}
cnt3=read();
for(int i=1;i<=cnt3;i++)
{
d=read();
if(d==1)
C=(C+fibo[i])%mod;
}
putd(mp[(qmul(A,B)-C+mod)%mod]);
}
int main()
{
fibo[0]=fibo[1]=1;
mp[1]=1;
for(int i=2;i<=2000010;i++)
{
fibo[i]=(fibo[i-1]+fibo[i-2])%mod;
mp[fibo[i]]=i;
}
int T=read();
while(T--)
solve();
return 0;
}