1. 程式人生 > 實用技巧 >HDU6768 The Oculus(Hash)

HDU6768 The Oculus(Hash)

Let's define the Fibonacci sequence \(F_1,F_2,\dots\) as \(F_1=1,F_2=2,F_i=F_{i-1}+F_{i-2}\) (\(i\geq 3\)).

It's well known that every positive integer \(x\) has its unique Fibonacci representation \((b_1,b_2,\dots,b_n)\) such that:

· \(b_1\times F_1+b_2\times F_2+\dots+b_n\times F_n=x\).

· \(b_n=1\)

, and for each \(i\) (\(1\leq i<n\)), \(b_i\in\{0,1\}\) always holds.

· For each \(i\) (\(1\leq i<n\)), \(b_i\times b_{i+1}=0\) always holds.

For example, \(4=(1,0,1)\), \(5=(0,0,0,1)\), and \(20=(0,1,0,1,0,1)\) because \(20=F_2+F_4+F_6=2+5+13\).

There are two positive integers \(A\) and \(B\) written in Fibonacci representation, Skywalkert calculated the product of \(A\)

and \(B\) and written the result \(C\) in Fibonacci representation. Assume the Fibonacci representation of \(C\) is \((b_1,b_2,\dots,b_n)\), Little Q then selected a bit \(k\) (\(1\leq k<n\)) such that \(b_k=1\) and modified \(b_k\) to \(0\).

It is so slow for Skywalkert to calculate the correct result again using Fast Fourier Transform and tedious reduction. Please help Skywalkert to find which bit \(k\)

was modified.

Input

The first line of the input contains a single integer \(T\) (\(1 \leq T \leq 10\,000\)), the number of test cases.

For each case, the first line of the input contains the Fibonacci representation of \(A\), the second line contains the Fibonacci representation of \(B\), and the third line contains the Fibonacci representation of modified \(C\).

Each line starts with an integer \(n\), denoting the length of the Fibonacci representation, followed by \(n\) integers \(b_1,b_2,\dots,b_n\), denoting the value of each bit.

It is guaranteed that:

· \(1\leq |A|,|B|\leq 1\,000\,000\).

· \(2\leq |C|\leq |A|+|B|+1\).

·\(\sum |A|,\sum |B|\leq 5\,000\,000\).

Output

For each test case, output a single line containing an integer, the value of \(k\).

Sample Input

1
3 1 0 1
4 0 0 0 1
6 0 1 0 0 0 1

Sample Output

4

學習一波QAQ

整體的思路大概就是設modify的是第k位,那麼有:\(A\times B=C+F_k\),移項後可得:\(F_k=A\times B -C\),預處理出斐波那契數列後直接查詢即可。但是注意到A,B都在1e6級別,這個範圍有點大,因此需要找一個模數P,使得Fib[1]~Fib[2e6]這個範圍內的元素模P兩兩不同餘(為啥是Fib[2e6]呢?因為k的範圍最大到2e6)。題解很巧妙地用了自然溢位,即P取unsigned long long的最大值\(2^{64}\)

(題目裡說不會有連續的1,又注意到這個數列是斐波那契數列,因此這個條件的含義就是一個數不會有其他的表示方法,比如(1110)和(1001)的值是一樣的,而前者有連續的1,就不會出現在輸入中。但這...會產生影響嗎..)

正常的Hash參照大佬部落格:https://www.cnblogs.com/stelayuri/p/13367956.html 可以用進階map也可以用雙Hash避免衝突。

#include <bits/stdc++.h>
using namespace std;
unsigned long long fib[2000005], A, B, C, k;
int main()
{
	int t;
	cin >> t;
	fib[1] = 1, fib[2] = 2;
	for(int i = 3; i <= 2000000; i++) fib[i] = fib[i - 1] + fib[i - 2];
	while(t--)
	{
		int na, nb, nc;
		A = B = C = 0;
		cin >> na;
		for(int i = 1; i <= na; i++)
		{
			int temp = 0;
			scanf("%d", &temp);
			if(temp) A += fib[i];
		}
		cin >> nb;
		for(int i = 1; i <= nb; i++)
		{
			int temp = 0;
			scanf("%d", &temp);
			if(temp) B += fib[i];
		}
		cin >> nc;
		for(int i = 1; i <= nc; i++)
		{
			int temp = 0;
			scanf("%d", &temp);
			if(temp) C += fib[i];
		}
		k = A * B - C;
		for(int i = 1; i <= 2000000; i++)
		{
			if(fib[i] == k)
			{
				cout << i << endl;
				break;
			}
		}
	}
	return 0;
 }