zoukankan      html  css  js  c++  java
  • PAT乙级(Basic Level)练习题-NowCoder数列总结

    题目描述


    NowCoder最近在研究一个数列:

    • F(0) = 7
    • F(1) = 11
    • F(n) = F(n-1) + F(n-2) (n≥2)
      他称之为NowCoder数列。请你帮忙确认一下数列中第n个数是否是3的倍数。

    输入描述:

    输入包含多组数据。
    每组数据包含一个整数n,(0≤n≤1000000)。


    输出描述

    对应每一组输入有一行输出。
    如果F(n)是3的倍数,则输出“Yes”;否则输出“No”。

    输入例子:

    0
    1
    2
    3
    4
    5

    输出例子:

    No
    No
    Yes
    No
    No
    No

    题目分析

    这是一个特殊初始条件的Fibonacci sequence.

    1.初始条件n的值比较小,可以直接枚举每个F(n)的值,然后输入n查询:

    #include <iostream>  
    #include <cstdio>  
    using namespace std;  
    int main (){  
        int n;  
      	int *a=new int[N];
      	a[0]=7;
        a[1]=11;
    	for(int i=2;i<N;i++)
    		a[i]=a[i-2]%3+a[i-1]%3;
        while(~scanf("%d", &n)){
    		cout<<a[n]<<endl;
        	if(a[n]%3==0)
    			cout<<"Yes"<<endl;
    		else
    			cout<<"No"<<endl;	
    	}
        return 0;  
    }  
    

    2.可以寻找到规律:(牛客网友“我要过pat”提供)

    这个真牛批,想不到还有这种规律。那Fibonacci数列是否有相似的规律呢?

    #include <iostream>  
    using namespace std;
    
    int main (){  
        int n;  
        while(cin>>n){
        if((n-2)%4==0)
        	cout<<"Yes"<<endl;
        else 
        	cout<<"No"<<endl;
    	}
        return 0;  
    }  
    

    3.用矩阵快速幂来求解,这题n的范围比较小(0≤n≤1000000)所以用第1种方法可以不超时求解,但是,倘若n很大,达到(1<=n<=1000,000,000,000,000,000)这个范围,那么显而易见,必定超时。而且根本开不到那么大的数组。学校的算法课,有另外一题类似的,可以思考一下:

    借此思路,用矩阵快速幂计算,稍微修改下就可以了。

     #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #define N 3
    #define maxn 2   
      
      
    using namespace std;  
      
    struct Matrix{  
        long long a[maxn][maxn];  
        void init(){    //初始化为单位矩阵   
            memset(a, 0, sizeof(a));  
            for(int i=0;i<maxn;++i){  
                a[i][i] = 1;  
            }  
        }  
    };  
      
    //矩阵乘法   
    Matrix mul(Matrix a, Matrix b){  
        Matrix ans;  
        for(int i=0;i<maxn;++i){  
            for(int j=0;j<maxn;++j){  
                ans.a[i][j] = 0;  
                for(int k=0;k<maxn;++k){  
                    ans.a[i][j] += a.a[i][k] * b.a[k][j];  
                    ans.a[i][j] %= N;   
                }  
            }  
        }   
        return ans;  
    }  
      
    //矩阵快速幂   
    Matrix qpow(Matrix a, long long n){  
        Matrix ans;  
        ans.init();  
        while(n){  
            if(n&1)   
                ans = mul(ans, a);  
            a = mul(a, a);  
            n /= 2;  
        }   
        return ans;  
    }  
      
    
    
    int main (){  
        long long n;  
      
        while(~scanf("%lld", &n)){
        Matrix a;  
        a.a[0][0] = 1;  
        a.a[0][1] = 1;  
        a.a[1][0] = 1;  
        a.a[1][1] = 0;  
        long long s0=7,s1=11;   
        if (n>1)  
            {  
            Matrix ans= qpow(a, n-1);  
            long long res=ans.a[0][0]*s1+ans.a[0][1]*s0;  
    //        printf("%lld",res); 
    		if(res%3==0)
    			cout<<"Yes"<<endl;
    		else
    			cout<<"No"<<endl;   
            }             
        else  
            cout<<"No"<<endl;  	
        	
        	
    	}
        return 0;  
    }  
    

    测评网站真的恶心,有时候循环输入用"cin>>"就可以,有时候又超时。。。得改"成~scanf("%lld", &n)"。另外一开始没想到对中间结果对3取模,导致数值过大溢出。用到unsigned long long 都不够。。。

    PS:检测一个数被3整除的算法

    1.检测一个数能否被3整除----位运算

    如果所有的偶数位出现1的次数为 even_count, 奇数位出现1的次数为 odd_count,两者只差如果是3的倍数,那么这个数就是3倍数。

    2.不用除法和求模运算,判断一个数能否被3整除

    现在给出一个数a,假设它能被3整除,结果是b,即a=3*b,那么从二进制乘法运算判断出,b的最低位与a的最低位一定是相同的,从而得到了b的最低位,将这个位左移1位变成次低位,那么a的次低位以上的比特减去这个位后在次低位上的结果一定是b的次低位。以此类推可以求出b的各个比特,如果最后能完成对b的各位的计算,那么a能够被3整除,否则不能被3整除。

    那么算法原理是什么呢?

  • 相关阅读:
    二叉平衡树
    红黑树
    [leetcode] LCP 比赛
    二叉搜索树
    面向对象的二叉树的实现
    二叉树的序列化与反序列化
    [leetcode] 基本计算器
    【pandas】玩转一行拆多行,多行并一行(分分合合你说了算)
    【VBA】数据溢出与解决
    【VBA】criterial 未找到命名参数
  • 原文地址:https://www.cnblogs.com/cafe3165/p/9732826.html
Copyright © 2011-2022 走看看