题解 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;
}
posted @ 2018-12-19 21:21  ThinkofBlank  阅读(241)  评论(0编辑  收藏  举报