这道题,发现暴力能过时,喷了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; }