数论专题hdu1005

  本题题意:给出公式a[i] = (A*a[i-1] + B*a[i-2]),输入A,B,n,求其第n项。

  代码如下:

  

/*
#include <iostream>
using namespace std;
int main()
{
    int A,B,n;
    
    A = B = 1;

    int k,z;

    for(int i=1;i<=1000;i++){
    
        for(int j=1;j<=1000;j++){

            A = i;
        
            B = j;

            int a[300] = {0,1,1};

            for(k=3;k<=200;k++){

                a[k] = (A*a[k-1] + B*a[k-2])%7;

                for(z=2;z<k;z++){

                    if(a[k] == a[z] && a[k-1] == a[z-1]){


                    cout << "A = " << A << "  B = " << B << "    " << a[k-1] << " " << a[k] << " z=" << z << " k=" << k << endl;

                        break;

                    }

                }

                if(z!=k)break;

            }
            
                
    
        }

    }
    
    return 0;
}


打了个表发现B为7的倍数时,且A > 1 && A < 7

表达式为:

    a[i] = A*a[i-1]%7 

    例子:

    A = 2

    1 1 2 4 1 2

    A = 3

    1 1 3 2 6 4 5 1 3

当A为7的倍数时,正常循环

而A和B同时为7的倍数时,除a[1],a[2],全为0

综合上述,情况我们就可以写出一个比较可靠的程序了
*/

#include <iostream>
using namespace std;

int i,j;

int main()
{

    int A,B,n;

    while(cin >> A >> B >> n && (A || B || n)){
//    首先n=2的情况,肯定是1,这是毫无疑问的
        if(n == 1 || n == 2){

            cout << 1 << endl;

            continue;

        }
//    然后从打表的结果来看,就是注释里的那个程序,当A和B为7的倍数,无论n是什么,结果必为0(此处已排除n取1,2的情况)。
        if(A % 7 == 0 && B % 7 == 0){

            cout << 0 << endl;

            continue;
    
        }
//    然后进入正题了(前两个if只是为了剪枝,去掉也不会影响代码的正确性),由于mod7,所以前后两个数的排列小于等于49,为了表达49个排列就要打印出前50项

//    举例:mod2的时候,就是 0 0 1 1 0,这样就包含了所有的4个排列
        int a[51] = {0,1,1};

        int l;

        for(i=3;i<=50;i++){

            a[i] = (A*a[i-1] + B*a[i-2]) % 7;
        
            for(j=2;j<i;j++){

                if(a[i] == a[j] && a[i-1] == a[j-1]){
                    
                    break;                                                                                                                                                                            
                }

            }    

            if(j!=i)break;
    
        }//    假设打印出的数组是1 1(j) 2 3 4 1 1(i),那么此时的i,j的位置就如前所示

        i -= 2;

        j -= 2;

//    然后进行减二操作是为了将循环的部分,复制到loop数组中,保险起见,这里我们把数组开到了51

        int loop[51];

        for(int k=j+1;k<=i;k++)
        {
        
            loop[k-j-1] = a[k];        

        }

//    然后当n在第一节,也就是包含了不循环部分和第一个循环部分的范围内时,直接按下标输出,通过打表发现不循环的部分只有在B%7==0的时候会有一个1的前缀,其他都是以1 1 开头的循环

        if(n <= i){

            cout << a[n] << endl;
    
        }

//    若n位与其后的部分,就对循环节的长度进行取模,这里i-j就是循环节的长度,由于loop数组是以0为下标开头的,因此n在减去j的基础上还要减1

        else{
    
            cout << loop[(n-j-1)%(i-j)] << endl;

        }

    }

    return 0;

}

这道题真的挺坑的,主要是之前实在想不出来就去查题解,然后题解一眼望上去居然是错的,然后就纠结了两天,终于灵光一闪,打表给ac了。

 

转载于:https://www.cnblogs.com/mtl6906/p/7527648.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值