zoukankan      html  css  js  c++  java
  • BZOJ 1406: [AHOI2007]密码箱 exgcd+唯一分解定理

    推出来了一个解法,但是感觉复杂度十分玄学,没想到秒过~

    Code: 

    #include <bits/stdc++.h>
    #define ll long long 
    #define N 50000 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    namespace Math
    { 
        ll pp,answer;  
        ll exgcd(ll a,ll b,ll &x,ll &y)
        {
            if(b==0)
            {
                x=1,y=0;
                return a;
            }
            ll ans=exgcd(b,a%b,x,y);
            ll tmp=x;
            x=y,y=tmp-a/b*y;
            return ans;
        }
        void solve(ll A,ll B,ll C)
        {   
            ll x,y,gcd,b,ans;
            gcd = exgcd(A,B,x,y);                        
            if(C%gcd!=0) 
            {
                answer=-1; 
                return; 
            }    
            x*=C/gcd,B/=gcd;
            if(B<0) B=-B;  
            ans=x%B;     
            if(ans<=0) ans+=B; 
            answer=ans,pp=B;     
        } 
    };   
    priority_queue<int,vector<int>,greater<int> >q;   
    map<int,int>mark;   
    vector<int>v;       
    int prime[N],vis[N],tot; 
    void init()
    {
        int i,j; 
        for(i=2;i<N;++i)
        {
            if(!vis[i]) prime[++tot]=i; 
            for(j=1;j<=tot&&prime[j]*i<N;++j)
            {
                vis[prime[j]*i]=1; 
                if(i%prime[j]==0) break;    
            }
        }
    }   
    int main()
    { 
        init();  
        // setIO("input"); 
        int n,i,j,h,flag=0;        
        scanf("%d",&n),h=n;     
        for(i=1;i<=tot&&h>=prime[i];++i)
        {
            if(h%prime[i]==0)
            {
                int cc=1;           
                for(;h%prime[i]==0;h/=prime[i]) cc*=prime[i];      
                v.push_back(cc);   
            }
        }   
        if(h!=1) v.push_back(h);   
        if(n%4==0) flag=1;   
        int len=v.size(); 
        for(i=0;i<(1<<len);++i)
        {
            int tmp=1;   
            for(j=0;(1<<j)<=i;++j)
            {
                if(i&(1<<j)) 
                    tmp*=v[j]; 
            }
            int a=tmp,b=n/tmp,dd;   
            Math::solve(a,b,2);                     
            if(Math::answer!=-1)      
            {
                ll anss=Math::answer*a-1;
                while(anss>=0&&anss<n) 
                { 
                	if(!mark[anss]) mark[anss]=1,q.push(anss);     
                	anss+=Math::pp*a; 
                }
            }         
            swap(a,b); 
            Math::solve(a,b,2);                     
            if(Math::answer!=-1)      
            {
                ll anss=Math::answer*a-1;
                while(anss>=0&&anss<n)
                { 
                	if(!mark[anss]) mark[anss]=1,q.push(anss);   
                	anss+=Math::pp*a; 
                }
            }              
            if(flag) 
            {
            	if(b%2==0) swap(a,b);    
            	a/=2,b*=2;             
    	        Math::solve(a,b,2);                        
    	        dd=Math::pp;         
    	        if(Math::answer!=-1)      
    	        {    
    	            ll anss=Math::answer*a-1;
    	            while(anss>=0&&anss<n) 
    	            {
    	            	if(!mark[anss]) 
    	            	{
    	            		mark[anss]=1; 
    	            		q.push(anss);   
    	            	}
    	            	anss+=Math::pp*a;    
    	            }
    	        }          
    	        swap(a,b); 
    	        Math::solve(a,b,2);                     
    	        if(Math::answer!=-1)      
    	        {
    	            ll anss=Math::answer*a-1;
    	            while(anss>=0&&anss<n) 
    	            {
    	            	if(!mark[anss]) 
    	            	{
    	            		mark[anss]=1; 
    	            		q.push(anss);   
    	            	}
    	            	anss+=Math::pp*a; 
    	            }
    	        }  
            }
        }   
        while(!q.empty()) 
        {
        	printf("%d
    ",q.top()); q.pop(); 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    android 自定义Dialog
    【Head First Java 读书笔记】(四)对象的行为
    【Head First Java 读书笔记】(三)primitive主数据类型和引用
    【Android学习】自定义checkbox
    【Java】java中的compareTo和compare的区别
    【Java】对Map按key和value分别排序
    【Andoid学习】GridView学习
    【实习项目记录】(三)调整网络图片固定宽高
    【实习项目记录】(二) JSON
    【实习项目记录】(一)加密算法MD5和RSA
  • 原文地址:https://www.cnblogs.com/guangheli/p/11502470.html
Copyright © 2011-2022 走看看