雖然這場我陪跑了(被教育了)
但是題解這東西想寫就寫了
沒出現的數字
題意:
判斷一個正整數的每一位數字中是否出現了0~9這10個數字,統計有多少個數字沒出現過。
題解:
使用bool數組標記是否出現過
- 使用memset初始化
- 使用string類型讀取數據,用s[i]-'0'作為下標
上板子:
using namespace std; bool num[10]; int main() { int T;cin >> T; while (T--) { int ans = 0; memset(num, 0, sizeof(num));//初始化num數組 string s; cin >> s; for (int i = 0;i < s.length();i++) num[s[i] - '0'] = 1; for (int i = 0;i < 10;i++) if (!num[i])ans++; cout << ans << endl; } return 0; }
喜歡的數字
題意:
規定 tql 喜歡 2 的整數次冪以及 2 的整數次冪 -1
給定一個數 num,求距離 num 最近的符合規定的數
題解:
進行預處理,記錄所有案例范圍內 tql 喜歡的數字
注:2^17=131,072,所以這題其實運算量不大,應該暴力也能AC
- 使用set容器存儲(可以用數組代替,記得對數組使用sort排序)
關於set容器的使用,可以參考網絡資料或者我的這篇《[C++STL] set 容器的入門》 - 使用lower_bound(begin,end,num)查找(lower_bound要對已經排序的數組使用)
上板子:
using namespace std; int main() { int a[50], p = 1,cnt=0; for (int i = 1;i < 18;i++) { p <<= 1; a[cnt++] = p - 1; a[cnt++] = p; } int t; cin >> t; int num; while (t--) { cin >> num; int num1 = *lower_bound(a, a+cnt-1, num);//二分查找,返回大於等於num的值的最小地址 int num2 = (num1 + 1 >> 1);//注意理解這里的num為什么要+1,可以自己代一組數據進去試試 cout << (num1 - num < num - num2 ? num1 : num2) << endl;//輸出距離較小的值 } return 0; }
上板子(使用set):
using namespace std; int main() { set<int>s; int a = 1; for (int i = 1;i < 18;i++) { a <<= 1;//位運算,相當於乘2 s.insert(a - 1); s.insert(a); } int t;cin >> t; int num; while (t--) { cin >> num; int num1 = *lower_bound(s.begin(), s.end(), num);//二分查找,返回大於等於num的值的最小地址 int num2 = (num1 + 1 >> 1);//注意理解這里的num為什么要+1,可以自己代一組數據進去試試 cout << (num1 - num < num - num2 ? num1 : num2) << endl;//輸出距離較小的值 } return 0; }
OJ新人
題意:
問最優的做題順序下的小分比當前順序下的小分,能少多少?
題解:
- 計算當前總分sum1
- 計算每道題的用時並記錄到數組a[]
- 對a進行排序
- 從用時最短的題目開始做
斐波那契湯
題意:
一個數列滿足:vi=vi-1/2+vi-2/3,i>=3;另外,每到5的倍數會 + c ,現給定前兩項與 c 求第 m 項
題解:
暴力迭代就是了
上板子:
using namespace std;int main() { int t;cin >> t; while (t--) { int a, b, c, m; cin >> a >> b >> c >> m; if (m == 1)cout << a << endl; else if (m == 2)cout << b << endl; else { for (int i = 3;i <= m;i++) { a = a / 3 + b / 2; if (i % 5 == 0)a += c; swap(a, b); } cout << b << endl; } } return 0; }
公共質因數的和
題意:
求a和b的所有公共質因數之和。
題解:
方法一:
- 先求a b的最大公因數,然后求最大公因數的質因數,然后相加求和
方法二:
- 使用短除法,除去算出a所有的質因數,判斷其是否為b的因數(思考一下為什么能夠保證每次的 i 都為質數)
主要是方法的問題,其實代碼實現沒有很大的難度
上板子(方法一):
using namespace std; typedef long long ll; int gcd(int a, int b)//輾轉相除法求最大公因數 { return !b ? a : gcd(b, a % b); } bool isPrime(int x) {//素數判斷 if (x < 2) return false; for (int i = 2;i <= sqrt(x);i++) if (x % i == 0) return false; return true; } int main() { int t;cin >> t; while (t--) { int num1, num2; ll sum = 0; cin >> num1 >> num2; int num = gcd(num1, num2); for (int i = 2;i <= sqrt(num);i++) { if (num % i == 0 && isPrime(i))sum += i; if (num / i == i)continue; if (num % (num / i) == 0 && isPrime(num / i))sum += num / i; } if (isPrime(num))sum += num; cout << sum << endl; } return 0; }
上板子(方法二):
using namespace std; int main() { int n; cin >> n; while (n--){ int a, b; cin >> a >> b; int ans = 0; for (int i = 2; i * i <= a; i++){ if (a % i == 0){//i是a的因數 if (b % i == 0) ans += i;//i是b的因數 while (a % i == 0) a /= i;//短除法 } } if (a > 1 && b % a == 0)//此時的a是b的因數(特判) ans += a; cout << ans << endl; } return 0; }
最大乘積
題意:
把一個正偶數m拆分成兩個質數之和(可以是相同的質數),輸出這兩個質數可能的最大乘積。
題解:
- 使用埃氏篩計算范圍內的全部質數
- 從m/2開始算(兩數和固定情況下,兩數越接近兩數乘積越大)
上板子:
using namespace std; typedef long long ll; const int N = 1000007; bool isprime[N]; int main() { memset(isprime, 1, sizeof(isprime)); for (int i = 2; i * i < N; i++) {//埃氏篩 if (isprime[i]) { for (int j = i * i; j < N; j = j + i) { isprime[j] = 0; } } } int T;cin >> T; while (T--) { ll num; cin >> num; for (ll i = num / 2;i > 1;i--) { if (isprime[i] && isprime[num-i]) { cout << i * (num-i) << endl; break; } } } return 0; }
制作:BDT20040
PS:這次線上賽被教育了,看到大佬30分鍾AK我直接心態炸了嗐