题意:
定 义 斐 波 那 契 数 列 : F 1 , F 2 , . . . , F 1 = 1 , F 2 = 2 , F i = F i − 1 + F i − 2 ( i ≥ 3 ) 定义斐波那契数列:F_1,F_2,...,F_1=1,F_2=2,F_i=F_{i-1}+F_{i-2}(i≥3) 定义斐波那契数列:F1,F2,...,F1=1,F2=2,Fi=Fi−1+Fi−2(i≥3)
众 所 周 知 , 任 意 的 正 整 数 x 可 由 斐 波 那 契 数 列 的 几 项 和 来 表 示 。 众所周知,任意的正整数x可由斐波那契数列的几项和来表示。 众所周知,任意的正整数x可由斐波那契数列的几项和来表示。
抽 象 地 , 即 对 任 意 的 正 整 数 x , 存 在 n 元 组 ( b 1 , b 2 , . . . , b n ) , 满 足 : 抽象地,即对任意的正整数x,存在n元组(b_1,b_2,...,b_n),满足: 抽象地,即对任意的正整数x,存在n元组(b1,b2,...,bn),满足:
例 如 : 4 = ( 1 , 0 , 1 ) , 5 = ( 0 , 0 , 0 , 1 ) , 20 = ( 0 , 1 , 0 , 1 , 0 , 1 ) , 因 为 20 = F 2 + F 4 + F 6 = 2 + 5 + 13. 例如: 4=(1,0,1), 5=(0,0,0,1), 20=(0,1,0,1,0,1) ,因为\ 20=F_2+F_4+F_6=2+5+13. 例如:4=(1,0,1),5=(0,0,0,1),20=(0,1,0,1,0,1),因为 20=F2+F4+F6=2+5+13.
T 组 测 试 样 例 。 T组测试样例。 T组测试样例。
每 组 测 试 样 例 输 入 三 行 数 据 , 每组测试样例输入三行数据, 每组测试样例输入三行数据,
每 行 包 括 一 个 长 度 n i , 和 一 个 长 度 为 n i 的 由 0 和 1 构 成 的 序 列 , 每行包括一个长度n_i,和一个长度为n_i的由0和1构成的序列, 每行包括一个长度ni,和一个长度为ni的由0和1构成的序列,
分 别 表 示 A 、 B 和 C 的 斐 波 那 契 序 列 的 表 示 。 分别表示A、B和C的斐波那契序列的表示。 分别表示A、B和C的斐波那契序列的表示。
已 知 C 的 斐 波 那 契 表 示 的 某 一 位 的 1 被 修 改 成 了 0 , 请 找 出 这 个 位 置 , 使 得 修 改 后 , 满 足 A × B = C 。 已知C的斐波那契表示的某一位的1被修改成了0,请找出这个位置,使得修改后,满足A×B=C。 已知C的斐波那契表示的某一位的1被修改成了0,请找出这个位置,使得修改后,满足A×B=C。
Sample Input
1
3 1 0 1
4 0 0 0 1
6 0 1 0 0 0 1
Sample Output
4
数据范围:
1 ≤ T ≤ 10000 , 1 ≤ ∣ A ∣ , ∣ B ∣ ≤ 1000000 , 2 ≤ ∣ C ∣ ≤ ∣ A ∣ + ∣ B ∣ + 1 , ∑ ∣ A ∣ , ∑ ∣ B ∣ ≤ 5000000 1≤T≤10000,\\ \ \\ 1≤|A|,|B|≤1000000,\\ \ \\2≤|C|≤|A|+|B|+1,\\ \ \\∑|A|,∑|B|≤5000000 1≤T≤10000, 1≤∣A∣,∣B∣≤1000000, 2≤∣C∣≤∣A∣+∣B∣+1, ∑∣A∣,∑∣B∣≤5000000
分析:
本 题 很 自 然 地 能 够 想 到 , 先 求 出 A 和 B , 记 X = A × B − C , 判 断 X 是 斐 波 那 契 数 列 的 第 几 项 。 本题很自然地能够想到,先求出A和B,记X=A×B-C,判断X是斐波那契数列的第几项。 本题很自然地能够想到,先求出A和B,记X=A×B−C,判断X是斐波那契数列的第几项。
计 算 A 和 B , 以 及 查 询 X 的 位 置 , 都 需 要 预 处 理 出 斐 波 那 契 数 列 的 部 分 项 。 计算A和B,以及查询X的位置,都需要预处理出斐波那契数列的部分项。 计算A和B,以及查询X的位置,都需要预处理出斐波那契数列的部分项。
考 虑 到 C 的 长 度 可 能 达 到 2000001 项 , 故 我 们 要 先 做 大 约 2 × 1 0 6 的 预 处 理 。 考虑到C的长度可能达到2000001项,故我们要先做大约2×10^6的预处理。 考虑到C的长度可能达到2000001项,故我们要先做大约2×106的预处理。
由 于 项 数 较 多 , 已 经 早 早 的 溢 出 了 1 0 18 , 因 此 我 们 计 算 时 , 需 要 对 斐 波 那 契 数 列 取 模 。 由于项数较多,已经早早的溢出了10^{18},因此我们计算时,需要对斐波那契数列取模。 由于项数较多,已经早早的溢出了1018,因此我们计算时,需要对斐波那契数列取模。
根 据 题 意 , 有 : ( A × B ) % P = ( C + X ) % P 根据题意,有:(A×B)\%P=(C+X)\%P 根据题意,有:(A×B)%P=(C+X)%P
即 : ( A × B ) % P − C % P = X % P 即:(A×B)\%P-C\%P=X\%P 即:(A×B)%P−C%P=X%P
我 们 计 算 出 X % P 后 , 在 预 处 理 的 斐 波 那 契 数 列 中 查 找 X % 所 在 的 位 置 即 可 。 我们计算出X\%P后,在预处理的斐波那契数列中查找X\%所在的位置即可。 我们计算出X%P后,在预处理的斐波那契数列中查找X%所在的位置即可。
( 题 解 直 接 建 议 用 无 符 号 的 长 整 型 , 让 其 自 然 溢 出 . . . ) (题解直接建议用无符号的长整型,让其自然溢出...) (题解直接建议用无符号的长整型,让其自然溢出...)
经 过 测 试 , 取 双 模 数 是 可 以 避 免 冲 突 的 。 ( 单 模 数 还 是 冲 突 一 大 堆 ) 经过测试,取双模数是可以避免冲突的。(单模数还是冲突一大堆) 经过测试,取双模数是可以避免冲突的。(单模数还是冲突一大堆)
因 此 我 们 用 p a i r 来 存 储 对 两 个 不 同 模 数 取 模 后 的 斐 波 那 契 数 列 。 因此我们用pair来存储对两个不同模数取模后的斐波那契数列。 因此我们用pair来存储对两个不同模数取模后的斐波那契数列。
对 A 、 B 、 C 对 两 个 模 数 P 1 和 P 2 取 模 , 接 着 在 预 处 理 的 斐 波 那 契 数 列 中 查 找 ( X 1 , X 2 ) 所 在 的 位 置 即 可 。 对A、B、C对两个模数P_1和P_2取模,接着在预处理的斐波那契数列中查找(X_1,X_2)所在的位置即可。 对A、B、C对两个模数P1和P2取模,接着在预处理的斐波那契数列中查找(X1,X2)所在的位置即可。
注意:
最 后 的 查 找 位 置 不 能 用 二 分 , 因 为 取 模 后 , 新 的 序 列 不 是 单 调 序 列 ! 最后的查找位置不能用二分,因为取模后,新的序列不是单调序列! 最后的查找位置不能用二分,因为取模后,新的序列不是单调序列!
直 接 遍 历 查 找 即 可 。 直接遍历查找即可。 直接遍历查找即可。
双模数:
代码:
#include
#include
#include
#include
#include
#define ll long long
#define P pair
#define x first
#define y second
using namespace std;
const int N=2e6, mod1=805306457, mod2=201326611;
int A[N+10],B[N+10],C[N+10];
P f[N+10];
void Init()
{
f[1].x=f[1].y=1,f[2].x=f[2].y=2;
for(int i=3;i<=N+5;i++)
{
f[i].x=(f[i-1].x+f[i-2].x)%mod1;
f[i].y=(f[i-1].y+f[i-2].y)%mod2;
}
}
int add_mod(int a,int b,int mod)
{
ll t=0;
t=a+b;
if(t>=mod) t%=mod;
return t;
}
int main()
{
Init();
int T,n1,n2,n3;
cin>>T;
while(T--)
{
P a,b,c;
int a1=0,a2=0,b1=0,b2=0,c1=0,c2=0;
scanf("%d",&n1);
for(int i=1;i<=n1;i++)
{
scanf("%d",&A[i]);
if(A[i])
{
a1=add_mod(a1,f[i].x,mod1);
a2=add_mod(a2,f[i].y,mod2);
}
}
a={a1,a2};
scanf("%d",&n2);
for(int i=1;i<=n2;i++)
{
scanf("%d",&B[i]);
if(B[i])
{
b1=add_mod(b1,f[i].x,mod1);
b2=add_mod(b2,f[i].y,mod2);
}
}
b={b1,b2};
scanf("%d",&n3);
for(int i=1;i<=n3;i++)
{
scanf("%d",&C[i]);
if(C[i])
{
c1=add_mod(c1,f[i].x,mod1);
c2=add_mod(c2,f[i].y,mod2);
}
}
c={c1,c2};
int d1=(ll)a.x*b.x%mod1;
int d2=(ll)a.y*b.y%mod2;
for(int i=1;;i++)
if(f[i].x==(d1-c.x+mod1)%mod1 && f[i].y==(d2-c.y+mod2)%mod2)
{
printf("%d\n",i);
break;
}
}
return 0;
}
自然溢出:
代码:
#include
#include
#include
#include
#include
#define ll unsigned long long
using namespace std;
const int N=2e6;
int A[N+10],B[N+10],C[N+10];
ll f[N+10];
void Init()
{
f[1]=1,f[2]=2;
for(int i=3;i<=N+5;i++) f[i]=f[i-1]+f[i-2];
}
int main()
{
Init();
int T,n1,n2,n3;
cin>>T;
while(T--)
{
ll a=0,b=0,c=0;
scanf("%d",&n1);
for(int i=1;i<=n1;i++)
{
scanf("%d",&A[i]);
if(A[i]) a+=f[i];
}
scanf("%d",&n2);
for(int i=1;i<=n2;i++)
{
scanf("%d",&B[i]);
if(B[i]) b+=f[i];
}
scanf("%d",&n3);
for(int i=1;i<=n3;i++)
{
scanf("%d",&C[i]);
if(C[i]) c+=f[i];
}
a*=b;
for(int i=1;;i++)
if(c+f[i]==a)
{
printf("%d\n",i);
break;
}
}
return 0;
}