?1. 題目鏈接:19937 藝術與籃球
該題目的難點主要在20240413這個日期需要結束程序跳出循環。最開始將該輸出ans的位置放在了for循環之外,此時的日期已經循環完了2024年所有的日期,則最后會統計多而導致結果錯誤。
AC代碼:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int day_1[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};//用數組預處理每月的天數
int day_2[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int sum_num[10]={13,1,2,3,5,4,4,2,2,2};//預處理每一個數字的文字筆畫
bool check_year(int year) //判斷閏年,便于選擇月份
{if((year%4 == 0 && year%100!=0)||(year%400 == 0)) return 1;else return 0;
}
int main()
{int ans=0,result=0,m,d,sum=0;for(int y=2000;y<=2024;y++){if(check_year(y) == 1) {for(m=1;m<=12;m++){for(d=1;d<=day_1[m];d++){sum=0;result=(y*10000)+(m*100)+d;while(result){sum += sum_num[result%10];result=result/10;}if(sum > 50) ans++;if ((y == 2024) && (m >= 4) && (d >= 13)) {cout<<ans;return 0;}//就是這一段輸出的位置需要注意}}}else if(check_year(y) == 0) {for(m=1;m<=12;m++){for(d=1;d<=day_2[m];d++){sum=0;result=(y*10000)+(m*100)+d;while(result){sum += sum_num[result%10];result=result/10; }if(sum > 50) ans++; if ((y == 2024) && (m >= 4) && (d >= 13)) {cout<<ans;return 0;}//已知2024是閏年,此處可以不需要這個輸出}}}}
}
這個方法有重復的代碼,需要簡化。
?2.題目鏈接:?3491 幸運數
該題目為填空題,可以直接進行輸出。
最開始的算法是將每一個數字進行拆分,算出位數,再進行判斷是否為偶數位。接著判斷該數的左右兩邊的和是否相等,最后進行個數統計。這里因為數字是從后往前分離的,且是偶數位,則可以先統計后面的,到一半的長度時停止,再換另一個計數器統計前一半。但測評結果是TLE。那么不能使用直接分離的方法。
TLE的枚舉代碼:
#include <iostream>
#include <cstdio>
#include <cmath>
#pragma GCC optimize(2)
using namespace std;
int check_number(int num)
{int ans=0;while(num){num=num/10;ans++;}if(ans%2 == 0) return ans;else return 0;
}
int main()
{int result=0;for(int i=10;i<=100000000;++i){int sum_1=0,sum_2=0,half;int number=i;if(check_number(i) != 0){half=check_number(i)/2;for(int j=1;j<=half;j++){sum_1 += number%10;number /=10;}for(int j=1;j<=half;j++){sum_2 += number%10;number /=10;}if(sum_1 == sum_2) result++;}else continue;}cout<<result;return 0;
}
?根據藍橋杯的官方題解,可以將數字轉換成字符串,則可以用字符串相關的函數直接得出結果數字的長度,進而判斷數字是否為偶數位。這個方法直接將時間復雜度從O(n)降到了O(1)。
#include<bits/stdc++.h>
using namespace std;
int main()
{int ans = 0;for (int i = 1; i <= 100000000; ++i) {string s = to_string(i); //直接轉換成字符串,便于統計數字長度,時間復雜度為O(1);int n = (int)s.size();if (n % 2) continue;int l = 0, r = 0;for (int j = 0; j < n; ++j) {if (j < n / 2) l += s[j] - '0';//字符轉換為數字else r += s[j] - '0';}if (l == r) ans++;}cout << ans << '\n';//4430091return 0;
}
3. 題目鏈接:1600 平方差
根據條件,最大的數字不超過2021,則可以將1到2021的所有可能性枚舉出來。
同時因為,用sum數組進行統計,只要滿足1到2021之間這個條件的數字就存入數組,不用管是否為1個拆分方式;最后遍歷數組,存了數字的數組就計數器加1。因為是開的全局數組可以不用memset數組為0。?
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1e7;
int sum[maxn];
int main()
{int result,ans=0;for(int i=1;i<=2021;i++){for(int j=0;j<i;j++){result=(i+j)*(i-j);if(result>=1&&result<=2021) sum[result]++;}}for(int i=1;i<=2021;i++){if(sum[i]!=0){ans++;}}cout<<ans;return 0;
}
!!一開始無思路的題
4. 題目鏈接:19732 小球反彈
首先根據題目,?將小球的運動方向拆解為x軸方向上的運動和y軸方向的運動。設小球在x軸方向的運動距離,y軸方向上的運動距離為
。根據勾股定理,小球每秒移動的距離
當小球?A?回到起點時,說明其在水平方向上的移動距離是長方形長度的偶數倍,在垂直方向上的移動距離是長方形寬度
的偶數倍。因為小球碰壁反彈的路徑與原來的路徑相同,那么相同的路徑走了偶數倍。
假設從開始到結束,小球總共花費了t?秒,那么有:
,
同時需要滿足:?,
由此,對?t?進行枚舉,直至找到滿足?15t?整除?343720且17t?整除?233333,和?
均為偶數的?t。
最終求得答案為?1100325199.77
。
需要注意的是,所求答案需要保留兩位小數,則距離的數據類型需要用double。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long int
bool check(ll a,ll b)
{if((a % b == 0)&&((a/b)%2 == 0)) return 1;else return 0;
}
int main()
{ll x=343720,y=233333;ll lx,ly;double dis;ll t;for(ll i=1;;i++){t=i;lx=15*t;ly=17*t;if(check(lx,x) && check(ly,y)) break;}dis=sqrt(15*t*15*t+17*t*17*t);printf("%.2lf",dis);return 0;
}
?