话说刚刚才注意到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;
}