線段樹專題太難了,那我來作數學吧!ios
但數學太難了,我......(扯c++
這兩天想了作了查了整理了幾道數學。算法
除了一些進階的知識,像莫比烏斯反演,杜教篩,min25學不會我跳了,一些基礎的思惟仍是能夠記錄一下。數組
ex_gcd ide
POJ 1061 青蛙的約會
POJ 2115 C Looooops函數
SGU 106 The equationoop
三連擊。spa
談談理解吧,原理我沒懂 (扯.net
就是經過exgcd求出來的gcd(a,b)=d,而c%d!=0說明無解。debug
再將a,b,c分別除以公約數d。 a/=d,b/=d,c/=d;
exgcd出來x=1, x*=c就是一個特解。其中x的最小正解(這裏包括0)是 (x%b+b)%b; 此時的y能夠相應用 y=(c-a*x)/b 反過來求解獲得。
同理 y的最小正解相應可獲得,y*=c 再 (y%a+a)%a;
這裏要特別注意儘可能讓a,b初始都是正的,並且特別注意要保證 ax+by=c這樣的式子的形式,特別是c的位置,c負的不要緊。
通解就能夠經過特解加 任意個單位 ,好比 x=x0+b*k; y=y0-a*k;
什麼什麼解系?我線代忘啦(哭
而後SGU 106 注意若是每一個參數負的,對應算出來的k區間要swap一下。由於你看那個負號在分母上呀。
還要用到ceil 和floor 。一直以來講精度偏差,我都不想用這個函數,後來仍是屈服了。
UVA 11752 The Super Powers
這題我思惟呀,雖然我岔了。手玩一下,發現指數爲合數就能成爲答案。
而後我一開始想用優先隊列!對素數的合數次冪加入答案。而後就沒了,WA了好一陣子。
其實合數的合數次冪也存在答案啊,好比6^4,能夠搞成6^(2*2 || 1*4) 而且這個是前面沒出現的!因此啊 要處理全部的數的答案。用set維護,不能用優先隊列了。
判溢出的細節
這我沒想到啊,題目是ull,一直想根據負數或者數變小了來判,難搞的很。
仍是看了題解才知道,用ull的上限,每次除這個數,預處理出每一個數最多的指數的次冪,最多指數次冪都小於4(最小的合數)了,就break掉。
別頭鐵判溢出啊,反過來處理最多指數到幾,這就頗有靈性對吧。(我沒有...
LightOJ 1370 Bi-shoe and Phi-shoe
POJ 2478 Farey Sequence
兩個歐拉篩,我幾個月的進步就是把我模板的篩從log升級到線性了紅紅火火恍恍惚惚。線性的還好理解,但min25和杜教目前必不可能懂555.
UVA 11426 GCD - Extreme (II)
這題好經典啊感受。我只能想到預處理歐拉函數,對每一個i 根號n的去找因數 那n^3/2就沒了啊。
而後又發現了新大陸思惟,對每一個數去找因數,是很差找的一個過程,但你對每一個因數去算他對別的數產生的貢獻是很好搞的!
再有一個gcd的公式 我要對每一個n找知足x與n 的gcd爲i的個數,gcd(n,x)=i ,gcd(n/i,x/i)=1; 這不是phi[n/i]! 每一個因數的貢獻就轉化爲了 i*phi[n/i]
而後就有了對因數1,2,3,4,5...... 去加貢獻 n+n/2+n/3+n/4+n/5+.....+1+....+0這個總複雜度咋算啊,md我竟然不會,反正比上面的優秀多了
還有,既能夠像我註釋裏同樣,統計sum【i】,O(1)回答,這樣預處理的複雜度就爲上面那個式子;大概500ms;
還查到了別人對歐拉函數求了前綴和,而後直接對每一個數O(n)統計,這個須要理解一下。只用200ms左右;
1 #include <bits/stdc++.h> 2 #define debug(x) cout << #x << ": " << x << endl 3 using namespace std; 4 typedef long long ll; 5 const int INF=0x3f3f3f3f; 6 const int MOD=1e9+7; 7 8 9 const int MAXN=4e6+7; 10 11 bool notprime[MAXN]; 12 //ll sum[MAXN]; 13 //ll b[MAXN]; 14 ll prime[MAXN/10]; 15 ll phi[MAXN]; 16 int cnt; 17 18 void getprime_phi() 19 { 20 cnt = 0; 21 phi[1] = 1; 22 notprime[0]=notprime[1]=1; 23 for(int i = 2;i < MAXN;i++) 24 { 25 if(!notprime[i]) 26 { 27 prime[cnt++] = i; 28 phi[i] = i-1; 29 } 30 for(int j = 0;j < cnt && i * prime[j] < MAXN;j++) 31 { 32 notprime[i*prime[j]] = 1; 33 if(i%prime[j]==0) 34 { 35 phi[i*prime[j]] = phi[i]*prime[j]; 36 break; 37 } 38 phi[i*prime[j]] = phi[i]*(prime[j]-1); 39 } 40 } 41 for(int i=2;i<MAXN;++i) phi[i]+=phi[i-1]; 42 } 43 44 int main() 45 { 46 getprime_phi(); 47 /*for(int i=1;i<MAXN;++i) 48 { 49 for(int j=i*2;j<MAXN;j+=i) 50 { 51 b[j]+=1ll*phi[j/i]*i; 52 } 53 } 54 55 for(int i=2;i<MAXN;++i) 56 sum[i]=sum[i-1]+b[i];*/ 57 int n; 58 while(~scanf("%d",&n)) 59 { 60 if(!n) break; 61 // printf("%lld\n",sum[n]); 62 ll ans=0; 63 for(int i=1;i<=n;++i) ans+=1ll*(phi[n/i]-1)*i; 64 printf("%lld\n",ans); 65 } 66 return 0; 67 }
POJ 2116 Death to Binary?
模擬題
將計算字符串的值 和 值轉化字符串 封裝成函數。
仍是string好用,對未賦值的string,不能經過下標訪問,但能夠用+=,直接粘在後面,賊棒,我一開始用char 數組,好難搞的啊。
而後我這題沒注意到輸入能夠爲0,沒測,而後出現了output limit exceed!活久見。而後發現本身原來的轉化寫假了,沒特判0。就會輸出賊多0,就沒了,竟然不是WA而是。
#include <string> #include <iostream> #include <algorithm> #include <cstring> #define debug(x) cout << #x << ": " << x << endl using namespace std; typedef long long ll; const int MAXN=100; const int INF=0x3f3f3f3f; const int MOD=1e9+7; ll f[60]; void init() { f[0]=1;f[1]=2; for(int i=2;i<50;++i) f[i]=f[i-2]+f[i-1]; } string s,t,ss,tt,goa; ll cal(string &str) { ll res=0; int len=str.size(); for(int i=0;i<len;++i) { if(str[i]=='1') res+=f[len-i-1]; } return res; } void standard(string &tmp, ll val) { tmp=""; for(int i=40;i>=0;--i) { if(val>=f[i]) { val-=f[i]; tmp+='1'; } else if(tmp!="") { tmp+='0'; } } if(tmp=="") tmp="0"; } int main() { init(); while(cin>>s>>t) { ll anss=cal(s); standard(ss,anss); ll anst=cal(t); standard(tt,anst); ll ans=anss+anst; //debug(ans); standard(goa,ans); int len=goa.size(); int lens=ss.size(); int lent=tt.size(); for(int i=0;i<len+2-lens;++i) cout<<' '; cout<<ss<<'\n'; cout<<"+ "; for(int i=0;i<len-lent;++i) cout<<' '; cout<<tt<<'\n'; cout<<" "; for(int i=0;i<len;++i) cout<<'-'; cout<<'\n'; cout<<" "<<goa<<'\n'<<'\n'; } return 0; } #include <string> #include <iostream> #include <algorithm> #include <cstring> #define debug(x) cout << #x << ": " << x << endl using namespace std; typedef long long ll; const int MAXN=100; const int INF=0x3f3f3f3f; const int MOD=1e9+7; ll f[60]; void init() { f[0]=1;f[1]=2; for(int i=2;i<50;++i) f[i]=f[i-2]+f[i-1]; } string s,t,ss,tt,goa; ll cal(string &str) { ll res=0; int len=str.size(); for(int i=0;i<len;++i) { if(str[i]=='1') res+=f[len-i-1]; } return res; } void standard(string &tmp, ll val) { tmp=""; for(int i=40;i>=0;--i) { if(val>=f[i]) { val-=f[i]; tmp+='1'; } else if(tmp!="") { tmp+='0'; } } if(tmp=="") tmp="0"; } int main() { init(); while(cin>>s>>t) { ll anss=cal(s); standard(ss,anss); ll anst=cal(t); standard(tt,anst); ll ans=anss+anst; //debug(ans); standard(goa,ans); int len=goa.size(); int lens=ss.size(); int lent=tt.size(); for(int i=0;i<len+2-lens;++i) cout<<' '; cout<<ss<<'\n'; cout<<"+ "; for(int i=0;i<len-lent;++i) cout<<' '; cout<<tt<<'\n'; cout<<" "; for(int i=0;i<len;++i) cout<<'-'; cout<<'\n'; cout<<" "<<goa<<'\n'<<'\n'; } return 0; }
UVA 10200 Prime Time
這都WA我,根號n試除法判素數便可,查了竟然WA在精度,不知道啥道理。
記住,當不得不使用除法,浮點數須要保留幾位小數四捨五入be rounded to,且你WA了,能夠加個小的eps???
總結:
而後除了歐拉篩的模板題,其餘好像都或多或少查了題解。
不過仍是堅持想了,本身實現了,WA了T了纔去查的。
只是感嘆本身仍是TCL,還要加油啊。算法競賽原本就是須要經驗積累的嘛!