程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [BZOJ]3737 [Pa2013]Euler,bzojpa2013

[BZOJ]3737 [Pa2013]Euler,bzojpa2013

編輯:C++入門知識

[BZOJ]3737 [Pa2013]Euler,bzojpa2013


從這個FB開始寫博客啦。

也不知道會堅持多久……

 

http://www.lydsy.com/JudgeOnline/problem.php?id=3737

 

因為是好玩的數學題所以剛看見的時候就想捉了……但是無限耽擱這兩天才處理掉。

交上去各種瑕疵CE……

改好發現數組開小各種RE……

然後各種TLE……

小看數據了= =。

 

看到題拿各種公式套,似乎是按因數來搜索。咦用2的冪次作深度上界估計似乎能搜?用質數前綴積上界似乎更小?

然後就暴搜吧……

原理是對任意phi(x)=n的x,它的所有素因子-1的積必被n整除。

所以跟先找哪個就沒關系了,多了一個下界剪枝。

然後枚舉可能的質數的時候只要枚舉不超過sqrt(n)的……否則有兩種情況。

1、此時x有兩個及以上的素因數,那麼一定有一個素因數-1是n小於sqrt(n)的因數,不可能找完大於sqrt(n)再回過來找它……

2、x是質數,也就是特判一下n+1是不是質數了。

 

雖然把第二種情況加了Miller_Rabin還是T了……

WTF!太假了!

然後發現能卡我的大多是類似那些高合成數的……總之要判的n+1一般不大。

於是把素數表打大一點,n+1小的時候直接在表裡找就過了。

 

最後回過頭證明一下搜索能硬上……

設F(k)為前k個質數積,f為其反函數。易知搜索樹的寬度深度都是f(n) (n還要變小呢)

而f(n)的話……記得以前推出來是logn/loglogn,錯了求不D。

 

然後按傳統要羞恥地貼代碼喽?……估計不對著代碼看也蠻難看懂的。

 

#include<cstdio> #include<algorithm> #include<cmath> #include<cstdlib> #include<cstring> using namespace std; typedef long long LL; #define rep(i,j,n) for(int i=j;i<=n;i++) char c; template<class T> inline void read(T&x){for(c=getchar();c<'0'||c>'9';c=getchar());for(x=0;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';}; bool t[4010010]; LL n,p[1000000],ans[1000000]; int T,tot,tott,len,S=10; void pre(){     memset(t,true,sizeof(t));     rep(i,2,4010000) if(t[i]){         p[++len]=i;         rep(j,i,4010000/i) t[i*j]=false;     } } inline LL muti_mod(LL a,LL b,LL c){     a%=c;     b%=c;     LL ret=0;     while(b){         if(b&1){ret+=a;if(ret>=c)ret-=c;}         a<<=1;         if(a>=c)a-=c;         b>>=1;     }     return ret; } inline LL pow_mod(LL x,LL n,LL mod){     if(n==1)return x%mod;     int bit[50],k=0;     while(n){         bit[k++]=n&1;         n>>=1;     }     LL ret=1;     for(;k>0;k--){         ret=muti_mod(ret,ret,mod);         if (bit[k-1]==1) ret=muti_mod(ret,x,mod);     }     return ret; } inline bool check(LL a,LL n,LL x,LL t){     LL ret=pow_mod(a,x,n),last=ret;     for(int i=1;i<=t;i++){         ret=muti_mod(ret,ret,n);         if(ret==1&&last!=1&&last!=n-1) return true;         last=ret;     }     if(ret!=1) return true;     return false; } inline bool prime(LL n){     if(n<2)return false;     if(n==2)return true;     if((n&1)==0) return false;     LL x=n-1;LL t=0;     while((x&1)==0){x>>=1;t++;}     for(int i=0;i<S;i++)     {         LL a=rand()%(n-1)+1;         if(check(a,n,x,t)) return false;     }     return true; } void find(LL n,int list,LL now){     if(n==1){ans[tot++]=now;return;}     if(1&n) return;     LL N=now,m,maxi=int(sqrt(n))+1;     rep(i,list,len) if(p[i]>maxi)break;else if(n%(p[i]-1)==0){         m=n/(p[i]-1);         N*=p[i];         find(m,i+1,N);         while(m%p[i]==0){             m/=p[i];N*=p[i];             find(m,i+1,N);         }         N=now;     }     if(n+1>=p[list]){         if(n+1>p[len]){if(prime(n+1))ans[tot++]=N*(n+1);}         else{if(t[n+1])ans[tot++]=N*(n+1);}     } } int main() {     read(T);     pre();     while(T--){         read(n);tot=0;         if(1&n){             if(n==1){puts("2");puts("1 2");}else puts("0"),puts("");             continue;         }         find(n,1,1);         sort(ans,ans+tot);         printf("%d\n",tot);         rep(i,0,tot-2) printf("%lld ",ans[i]);         if(tot)printf("%lld\n",ans[tot-1]);else{puts("");};     } }

 


[一筆畫問題][歐拉路徑,歐拉回路]圖 解

沒有度數為奇數的頂點的圖含有歐拉回路.Kn當n是奇數時,每個頂點的度都是n-1是偶數,此時Kn含有歐拉回路.
只有兩個度數為奇數的頂點的圖有歐拉路但沒有歐拉回路.由上題,n不能是奇數,n是偶數時,Kn有n個度數為奇數的頂點,所以n=2.
 

[一筆畫問題][歐拉路徑,歐拉回路]圖 解,50分

第一個 N是 3第二個N是 2吧 ?
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved