UVa 11582 거대 한 피 보 나치 수열

3753 단어 #UVa수학.
제목.
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41990
해제
수학 문제 로 서 이것 은 비교적 흥미 로 운 것 입 니 다. 우선% n 의 의미 에서 피 보 나 치 는 순환 절 이 있 을 것 입 니 다. 이 순환 절 은 얼마 입 니까?두 개의 똑 같은 것 만 있 으 면 뒤에 계속 누 적 된 수열 도 똑 같 기 때문에 순환 절 이 나타 날 수 있 기 때문이다.n ^ 2 개의 서로 다른 두 개의 조합 이 있 기 때문에 n ^ 2 항 정도 에 반드시 순환 절 이 나타 날 것 입 니 다. 실측 n = 1000 이면 순환 절 은 1501 로 생각 보다 작 습 니 다.순환 절 을 찾 으 면% 가 됩 니 다. k = a ^ b% M (순환 절 길이) 은 빠 른 속도 로 남 습 니 다.계산 해서 f [k] 를 직접 출력 하면 됩 니 다.
데이터 형식 은 경상 입 니 다. 원래 int Pow (int a, ull p, int Mod) 를 썼 습 니 다. 제 가 생각 하 는 것 은 호출 할 때 int k = Pow (a% M, b, M) 를 썼 기 때 문 입 니 다. 분명히 a% M 은 매우 작 을 것 입 니 다. 그러나 저 는 a 입력 을 무시 할 때 unsigned long 형식 입 니 다. = int 를 강제로 만 들 면 신기 한 일이 생 길 수 있 습 니 다.(역시 취 했다).
또한 이 문제 의 데이터 그룹 수가 많 고 n 이 비교적 작다 면 n 에 대응 하 는 피 보 나치 수열 을 현 산 이 아니 라 미리 처리 해 야 한다.
코드 - -
#include
#include
#include
#include
#include
typedef unsigned long long ll;
using namespace std;
const int maxn=1000+10;

ll a,b;
int f[maxn*maxn],n,M;

int pow(ll a,ll p,int Mod)
{
    int ret=1;
    while(p)
    {
        if(p & 1)ret*=a,ret%=Mod;
        a*=a;a%=Mod;
        p>>=1;
    }
    return ret;
}

inline void solve()
{
    cin>>a>>b>>n;
    if(n==1||!a){printf("0
"
);return ;} f[1]=1,f[2]=1; for(int i=3;i<=n*n+10;i++) { f[i]=f[i-1]+f[i-2];f[i]%=n; if(f[i]==f[2]&&f[i-1]==f[1]) {M=i-2;break;} } int k=pow(a%M,b,M); printf("%d
"
,f[k]); } int main() { int T;cin>>T; while(T--) solve(); return 0; }

좋은 웹페이지 즐겨찾기