話說剛剛纔注意到Project Euler的提交時間記錄的是UTC
第11題
這一題與第8題類似,不過這個求的是八個方向上的最值。雖然這個也可以有類似移動窗口的做法,但是考慮到長度只有四,
(期間因爲cal函數沒有return,debug十餘分鐘-_-!!!)
long long num[21][21];
long long cal(int x,int y,int dx,int dy){
long long ans=1;
if (x+3*dx>=1&&x+3*dx<=20&&y+3*dy>=1&&y+3*dy<=20)
for (int cnt=1;cnt<=4;cnt++,x+=dx,y+=dy){
ans*=num[x][y];
}
return ans;
}
int main(){
for (int i=1;i<=20;i++){
for (int j=1;j<=20;j++){
num[i][j]=read();
}
}
long long ans=1,tmp=0;
for (int i=1;i<=20;i++){
for (int j=1;j<=20;j++){
tmp=max(max(max(cal(i,j,-1,-1),cal(i,j,-1,0)),max(cal(i,j,0,-1),cal(i,j,-1,1))),max(max(cal(i,j,1,-1),cal(i,j,0,1)),max(cal(i,j,1,0),cal(i,j,1,1))));
//上一行就是將以[i][j]爲起點的八個方向的最值保存到tmp中
ans=max(tmp,ans);
}
}
cout<<ans<<endl;
return 0;
}
第12題
這個題是求第一個有超過500個因子的triangle number。
triangle number定義爲
若將一個數x表示爲
那麼x的因子數量爲
我在Project Euler 1-5題#3中解釋並證明過
雖然利用Project Euler 6-10題#7中的性質可以優化到近似
int check(int x){
int ans=1,num=x;
for (int i=2,tmp;i*i<=x;i++){
tmp=1;
while (num%i==0){
num/=i;
tmp++;//tmp即yi
}
ans*=tmp;
}
if (num!=1) ans*=2;
return ans;
}
int main(){
for (int i=1;;i++){
int ans=i*(i+1)/2;
if (check(ans)>500) {
cout<<i<<' '<<ans<<endl;
return 0;
}
}
}
第13題
題目來源ProjectEuler
(由於題目數據過大,我只截取了部分內容)
這個題給出了100個50位數,求這100個數和的前10位。
由於C/C++ 標準庫裏面沒有高精度類,而unsigned long long類型也只能保存最多20位數。
而即使是long double類型也沒有50位的精度。那用C/C++語言這個題有兩個做法(Python、Java那些自帶高精度類的就直接算吧)。
一、手寫高精度類,在大多數比賽中,由於數據的隨機性以及罰時,大多會採用這一方法
二、至計算前十幾位的結果,取最後結果的前10位輸出。儘管可能碰到前若干位求和後的結果是9999999999……,後面某位的進位一路爆過去的情況,不過這個方法正確的概率依然是蠻高的。對於這個題已知數據的情況,可以試一試。我選擇了前14位求和,輸出結果的前十位。反正這麼做對了2333(逃
int main(){
char s[55];
long long ans=0,tmp;
for (int i=1;i<=100;i++){
cin>>s;
tmp=0;
for (int j=0;j<=13;j++){
tmp*=10;
tmp+=s[j]-'0';
}
ans+=tmp;
}
int cnt=14;s[14]=0;
while(ans){
s[--cnt]=ans%10+'0';
ans/=10;
}
s[cnt+10]=0;
cout<<s+cnt<<endl;
return 0;
}
第14題
這個題來源於一個很經典的問題,名字很多,應該還是叫3n+1問題的人多吧。
具體可參考維基百科
題目求的是小於1,000,000的所有數裏面,將其計算到1,步驟最多的那個數。
我採用了一個半記憶化的dfs。對於所有10,000,000以內的數所需要的步數進行儲存,10,000,000及以上的數的結果不儲存。
int num[10000000];
int cal(long long x){
if(x<=9999999){
if (num[x]) return num[x];
if (x&1) return num[x]=1+cal(x*3+1);
else return num[x]=1+cal(x/2);
}
else{
if (x&1) return 1+cal(x*3+1);
else return 1+cal(x/2);
}
}
int main(){
num[1]=1;int ans=1,len=0;
for (int i=1;i<1000000;i++){
if(cal(i)>len) len=num[i],ans=i;
}
cout<<ans<<endl;
return 0;
}
第15題
這個題問的是在一個20*20的網格中,從左上角走到右下角有幾種走法,每次只能往右或者往下。
一共要走40步,區別就在於哪幾步往右,哪幾步往下。結果就是
考慮到
我們可以採用dp的方式。
long long dp[50][50];
int main(){
dp[0][0]=1;
for (int i=1;i<=40;i++){
dp[i][0]=1;
for(int j=1;j<=i;j++){
dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
}
}
cout<<dp[40][20];
return 0;
}