您的位置:首页 > 其它

51Nod 1355 斐波那契的最小公倍数

2018-01-27 10:35 357 查看
lcm实际上是求集合的并集,gcd实际上是求集合的交集,由容斥可得:lcm(S)=∏x∈Sgcd(x)(−1)|x|−1。

由斐波那契数列满足gcd(Fi,Fj)=Fgcd(i,j),设:

f(i)=∑x∈S(−1)|x|−1[gcd(x)=i]

x(i)=∑nj=1[i|Aj]

k(i)=∑x∈S(−1)|x|−1[i|gcd(x)]=Coddx(i)−Cevenx(i)+1=[x(i)>0]

f(i)=∑⌊ni⌋j=1μ(j)k(ij)

总时间复杂度为O(106log106)。

#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
//--Container
#include<unordered_map>
#include<vector>
//
typedef long long ll;
typedef pair<ll,ll> pl;
const ll md=1e9+7;const int up=1e6;

int mu[up+10],pr[up+10],fr[up+10],kr[up+10],pn;bool bd[up+10];
struct eg{int v,nx;}gp[14000010];int cnt,hd[up+10];
inline void psh(int u,int v){++cnt;gp[cnt].v=v,gp[cnt].nx=hd[u],hd[u]=cnt;};
inline ll qni(ll a,ll b){ll r=1;for(;b;b>>=1,a=a*a%md)if(b&1)r=r*a%md;return r;};
void init(){
int i,j,k;for(pn=0,i=2;i<=up;++i){
if(!bd[i]){mu[i]=-1,pr[pn++]=i;}
for(j=0;j<pn&&(ll)pr[j]*i<=up;++j){
mu[pr[j]*i]=-mu[i],bd[pr[j]*i]=1;
if(!(i%pr[j])){mu[pr[j]*i]=0;break;}
}
}
for(mu[1]=1,i=1;i<=up;++i)for(j=i;j<=up;j+=i)psh(j,i);
for(fr[0]=0,fr[1]=1,i=2;i<=up;++i){
fr[i]=fr[i-1]+fr[i-2];if(fr[i]>=md)fr[i]-=md;
}
};

void cl(){
int i,j,k,a,n;ll rs=1;scanf("%d",&n);
for(i=0;i<n;++i){
scanf("%d",&a);for(j=hd[a];j;j=gp[j].nx)kr[gp[j].v]++;
}
for(i=1;i<=up;++i){
for(k=0,j=i;j<=up;j+=i)k+=mu[j/i]*(kr[j]>0?1:0);
rs*=qni(fr[i],k+md-1);rs%=md;
}
printf("%lld\n",rs);
};

int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
init();cl();
return 0;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: