C - Calculate Prime S ( 斐波那契数列性质

Define S[n] as the number of subsets of {1, 2, ..., n} that contain no consecutive integers. For each S[n], if for all i (1 ≤ i < n) gcd(S[i], S[n]) is 1, we call that S[n] as a Prime S. Additionally, S[1] is also a Prime S. For the Kth minimum Prime S, we'd like to find the minimum S[n] which is multiple of X and not less than the Kth minimum Prime S. Please tell us the corresponding (S[n] ÷ X) mod M.

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases.

For each test case, there are 3 integers K (1 ≤ K ≤ 106), X (3 ≤ X ≤ 100) and M (10 ≤ M ≤ 106), which are defined in above description.

<h4< dd="">Output

For each test case, please output the corresponding (S[n] ÷ X) mod M.

<h4< dd="">Sample Input

1
1 3 10

<h4< dd="">Sample Output

1


SOLUTION:
原文:https://blog.csdn.net/zy691357966/article/details/44857739

2.斐波拉契性质
gcd(fib(n),fib(m))=fib(gcd(n,m)) (从1开始计算的即 1 1 2 3 5 8序列)
所以只有当 gcd(n,m)=1或2时 fib[n]与fib[m]互质
S[n]=fib[n+2]
所以若S[n] 要是一个 PrimeS
则n+2必须是一个质数或者4 ,自己画画就知道为什么4是特殊的了
所以构造一个特殊的素数表
P[i] 3 4 5 7 11 13...................
所以第K个PrimeS 就是fib[P[k]]

3.如何寻找整除X的数

从 fib[P[k]开始一个一个找 使得fib[P[k]]%X==0 的数即可

记录ansi=i;

4.同余公式的引用

(a/b)%c=(a%(b*c))/b

根据ansi 计算即可

 

CODE:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define LL long long
using namespace std;
const int maxn=16000001;
int K,X,M;
int p[2000001],tot=0;
bool yn[maxn];
struct node
{
    LL mat[3][3];
};
node matmult(node a,node b,int mod)
{
    node c;
    memset(c.mat,0,sizeof(c.mat));
    for(int i=1; i<=2; i++)        for(int j=1; j<=2; j++)            for(int k=1; k<=2; k++)            c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
    return c;
}
node quickmatpow(node a,int n,int mod)
{
    node c;
    memset(c.mat,0,sizeof(c.mat));
    c.mat[1][1]=1;
    c.mat[1][2]=0;
    c.mat[2][1]=0;
    c.mat[2][2]=1;
    while(n!=0)
    {
        if(n&1==1) c=matmult(c,a,mod);
        a=matmult(a,a,mod);
        n=n>>1;
    }
    return c;
}
void get_prime()
{
    for(int i=2; i<maxn; i++)
    {
        if(yn[i]==false)
        {
            p[++tot]=i;
            for(int j=i; j<maxn; j=j+i)          yn[j]=true;
        }
    }   //  printf("%d\n",tot);
    p[1]=3;
    p[2]=4;
}
void init()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
}
int main()
{


//  init();
get_prime();
int T;
cin>>T;
while(T--)
{
    int ansi;
    int temp;
    node a,c;
    memset(a.mat,0,sizeof(a.mat));
    memset(c.mat,0,sizeof(c.mat));
    a.mat[1][1]=1,a.mat[1][2]=1,a.mat[2][1]=1,a.mat[2][2]=0;
    scanf("%d%d%d",&K,&X,&M);
    for(int i=p[K];; i++)
    {
        c=quickmatpow(a,i-2,X);
        temp=((c.mat[1][1]+c.mat[1][2]))%X;
        if(temp==0)
        {
            ansi=i;
            break;
        }
    }
    c=quickmatpow(a,ansi-2,M*X);
    temp=((c.mat[1][1]+c.mat[1][2]))%(M*X);
    printf("%d\n",temp/X);
}
return 0;

}

  

 

 

 





转载于:https://www.cnblogs.com/zhangbuang/p/11240476.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值