21-22(1)第4次線上賽題解


雖然這場我陪跑了(被教育了)

但是題解這東西想寫就寫了 


沒出現的數字

題意:

判斷一個正整數的每一位數字中是否出現了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新人

題意:

問最優的做題順序下的小分比當前順序下的小分,能少多少?

題解:

  1. 計算當前總分sum1
  2. 計算每道題的用時並記錄到數組a[]
  3. 對a進行排序
  4. 從用時最短的題目開始做

斐波那契湯

題意:

一個數列滿足: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拆分成兩個質數之和(可以是相同的質數),輸出這兩個質數可能的最大乘積。

題解:

  1. 使用埃氏篩計算范圍內的全部質數
  2. 從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我直接心態炸了嗐


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM