zoukankan      html  css  js  c++  java
  • [Lydsy1704月赛] 最小公倍佩尔数

    4833: [Lydsy1704月赛]最小公倍佩尔数

    Time Limit: 8 Sec  Memory Limit: 128 MB
    Submit: 202  Solved: 99
    [Submit][Status][Discuss]

    Description

     令(1+sqrt(2))^n=e(n)+f(n)*sqrt(2),其中e(n),f(n)都是整数,显然有(1-sqrt(2))^n=e(n)-f(n)*sqrt(2)。令g(

    n)表示f(1),f(2)…f(n)的最小公倍数,给定两个正整数n和p,其中p是质数,并且保证f(1),f(2)…f(n)在模p意义
    下均不为0,请计算sigma(i*g(i)),1<=i<=n.其在模p的值。
     

    Input

    第一行包含一个正整数 T ,表示有 T 组数据,满足 T≤210 。接下来是测试数据。每组测试数据只占一行,包含
    两个正整数 n 和 p ,满足 1≤n≤10^6,2≤p≤10^9+7 。保证所有测试数据的 n 之和不超过 3×10^6  。
     
     

    Output

    对于每组测试数据,输出一行一个非负整数,表示这组数据的答案。

     
     

    Sample Input

    5
    1 233
    2 233
    3 233
    4 233
    5 233

    Sample Output

    1
    5
    35
    42
    121

    HINT

     

    Source

     
     
        一眼看去就是一道毒瘤数论题233333
        首先要把 f() 这个数列搞出来,把f(n)的表达式写出来,发现是 ∑ [i%2==1] * C(n,i) * (sqrt(2)^(i-1))。
        (打个表就可以发现 f(n) = 2 * f(n-1) + f(n-2) 了嘛 2333)
     
        显然类菲波那切数列(满足 f(n+m) = f(n+1) * f(m) + f(n) * f(m-1)) 都是满足 gcd(f(x) , f(y)) = f( gcd(x,y) )的啊,之后对指数做min_max容斥,就可以得到一坨子关于子集gcd乘乘除除的玩意,看起来还有点麻烦。。。
        于是可以再设 f(n) = π h(d) * [d|n] ,然后样把所有 f(gcd) 替换成 π h(),化简一下就可以发现 : g(i) = π h(j) * [j<=i] ,于是就可以直接做了QWQ
     
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1e6+5;
    
    inline int add(int x,int y,const int ha){ x+=y; return x>=ha?x-ha:x;}
    inline void ADD(int &x,int y,const int ha){ x+=y; if(x>=ha) x-=ha;}
    inline int mul(int x,int y,const int ha){ return x*(ll)y%ha;}
    
    inline int ksm(int x,int y,const int ha){
    	int an=1;
    	for(;y;y>>=1,x=mul(x,x,ha)) if(y&1) an=mul(an,x,ha);
    	return an;
    }
    
    int T,f[maxn],h[maxn],n,ans=0,p,now;
    
    inline void solve(){
    	f[1]=1; for(int i=2;i<=n;i++) f[i]=add(add(f[i-1],f[i-1],p),f[i-2],p);
    	
    	for(int i=1,inv;i<=n;i++){
    		h[i]=f[i],inv=ksm(h[i],p-2,p);
    		
    		for(int j=i*2;j<=n;j+=i) f[j]=mul(f[j],inv,p);
    		
    		now=mul(now,h[i],p);
    		ADD(ans,mul(now,i,p),p);
    	}
    }
    
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d%d",&n,&p);
    	    
    		ans=0,now=1,solve();
    		
    		printf("%d
    ",ans);
    	}
    	
    	return 0;
    } 
    

      

  • 相关阅读:
    docker生态系统
    访问远程的docker
    docker实践4
    docker实践3
    docker实践
    Spark快速入门
    shuffle和sort分析
    hadoop原理
    apacheds的客户端
    LDAP apacheds解决方案
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9211916.html
Copyright © 2011-2022 走看看