题意:
S[i]为1到 i 的自然数序列中不存在连续元素的子集的个数。S[n]与所有S[i](i<n)互质,则为Prime S。求(S[n]/X)%M;
思路:
集合性质:一个含n个元素的集合的子集数为2的n次方。由集合性质推得S[i+1]=S[i]+S[i-1],则S[i]是斐波那契数。
打表结果:
S[1]=2, S[2]=3, S[3]=5, S[4]=8, S[5]=13,S[6]=21......
fib[1]=1,fib[2]=1,fib[3]=2,fib[4]=3,fib[5]=5,fib[6]=8,fib[7]=13......
从斐波那契数列的第五项(fib[4]为Prime S)开始,每项斐波那契为Prime S(Prime S表示S[n]与所有S[i]互质)的条件为当且仅当它的项数为质数,因此采用素数打表的方法得到第k个Prime S的斐波那契数的项数。然后用矩阵乘法求出第k个S的值对应的下一个斐波那契数,然后枚举该斐波那契数,直到能被X整除。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
typedef long long LL;
const LL N=16000000;
LL p[N];
bool prime[N];
LL k=1;
void isprime() //素数打表
{
LL i,j;
p[0]=1;
memset(prime,true,sizeof(prime));
for(i=2;i<N;i++)
{
if(prime[i])
{
p[k++]=i; //p数组保存素数
for(j=i+i;j<N;j+=i)
{
prime[j]=false;
}
}
}
p[1]=3;p[2]=4;
}
typedef struct
{
LL m[2][2];
}Matrix;
Matrix per={1,0,0,1};
Matrix a={1,1,1,0};
Matrix multi(Matrix a,Matrix b,LL MOD) //使用矩阵乘法求斐波那契数
{
Matrix c;
LL i,j;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
c.m[i][j]=0;
for(k=0;k<2;k++)
{
c.m[i][j]+=a.m[i][k]*b.m[k][j];
c.m[i][j]%=MOD;
}
}
}
return c;
}
Matrix matrix_mod(LL k,LL MOD) //第k个斐波那契数取模
{
Matrix p=a,ans=per;
while(k)
{
if(k&1)
{
ans=multi(ans,p,MOD);
k--;
}
k>>=1;
p=multi(p,p,MOD);
}
return ans;
}
int main()
{
LL K,X,M,t,i,ret,r;
isprime();
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&K,&X,&M);
Matrix ans;
for(i=p[K];;i++) //枚举斐波那契数S[n]
{
ans=matrix_mod(i-1,X);
if((ans.m[0][0]%X==0))//直至能整除
{
r=i;
break;
}
}
ans=matrix_mod(i-1,M*X); //斐波那契性质
ret=ans.m[0][0]/X;
printf("%lld\n",ret);
}
return 0;
}