题解 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;
}