1. 程式人生 > >題解 P4994 【終於結束的起點】

題解 P4994 【終於結束的起點】

這道題,發現暴力能過時,噴了3k的血。。。本人花了近半小時打表找規律。。。然後真找出來一些了。。。

1.f[x^n]=f[x]*(x^(n-1))

2.設x,y為不相同的質數,則f[x^a*y^b]=lcm(f[x^a],f[y^b])。

3.對於一個質數x,他的f[x]極小(似乎都很小??)

對於一個n,我們就可以將他進行質因數分解:設n=x^ay^b...

然後我們暴力求出f[x],f[y],套上規律一,求出f[x^a],f[y^b],再套規律二,就可以求出來了。。。

分析:因為n<=706150,所以我們最多隻需要暴力7個素數,而經試驗,每個素數的f最多隻有自身的2倍多(除了5是4倍。。。) 所以暴力執行次數最多為14*n(穩過。。。)

對於求f[x^a]套個log的快速冪,lcm也是log...所以,所有資料都是穩過的。。。

奉上程式碼:

#include<bits/stdc++.h>
using namespace std; const int N=10000000; int M; bool is_not_prime[N]; int f[N],zhi[N],e; inline void sai(int maxe){ for(int i=2;i<=maxe;++i){ if(!is_not_prime[i]){ zhi[++e]=i; for(int j=i;j<=maxe/i;++j){ is_not_prime[i*j]=1; } } } } inline int gcd(int x,int y){ return x%y==0?y:gcd(y,x%y); } inline int lcm(int x,int y){//lcm return x/gcd(x,y)*y; } inline int bl(int x){//暴力計算 f[1]=1; for(int i=2;i;++i){ f[i]=f[i-1]+f[i-2]; f[i]%=x; if(f[i]==1&&f[i-1]==0){ return i-1; } } } inline int ksm(int x,int y){ int ans=1; while(y){ if(y&1){ ans*=x; } x*=x; y>>=1; } return ans; } inline int div(int x){ int ans=1; for(int i=1;i<=e;++i){ if(zhi[i]>x){ break; } if(x%zhi[i]==0){//分解質因數 int tim=0; while(x%zhi[i]==0){//求冪 tim++; x/=zhi[i]; } int ti=bl(zhi[i]); ti*=ksm(zhi[i],tim-1); ans=lcm(ans,ti); } } return ans; } int main(){ //2^n=3*2^(n-1) //3^n=8*3^(n-1) //5^n=20*5^(n-1) sai(706150);//篩法篩質數 int x; scanf("%d",&x); printf("%d\n",div(x)); return 0; }