1. 程式人生 > 其它 >AcWing第21場周賽總結

AcWing第21場周賽總結

3997. 整數冪

題目連結:

https://www.acwing.com/problem/content/4000/

1. 題目描述

給定兩個整數 k 和 l,請判斷是否存在一個整數 n,滿足 kn=l。

輸入格式

第一行包含整數 T,表示共有 T 組測試資料。

每組資料佔兩行,第一行包含整數 k,第二行包含整數 l。

輸出格式

每組資料輸出一行結果,如果存在 n,則輸出 YES,否則輸出 NO

資料範圍

前三個測試點滿足,2≤k,l≤100。
所有測試點滿足,1≤T≤10,\(2≤k,l≤2^{31−1}\)

輸入樣例:

2
5
25
3
8

輸出樣例:

YES
NO

2. 思路及題解

思路:

  • 直接使用樸素演算法(暴力法)

    即可。

    • 如果l不能整除k,說明不可能滿足\(k^{n}=l\),直接輸出NO即可。

    • 否則,計算k的n次冪,直到\(k^{n}≥l\)

      1. \(k^{n}>l\),說明不滿足條件,輸出NO

      2. \(k^{n}=l\),說明滿足條件,輸出YES

題解:

#include <iostream>
#include <map>
#include <vector>
#include <utility>
#include <algorithm>
#include <cmath> 
#include <string>

using namespace std;
typedef long long ll;

int main()
{
	ll T;
	ll k, l;
	cin >> T;
	while (T--)
	{
		cin >> k >> l;
		if (l % k != 0) 
		{
			cout << "NO" << endl;
			continue;
		}
		ll sum = 1;
		while (sum < l)
		{
			sum *= k;
			if (sum == l) 
			{
				cout << "YES" << endl;
				break;
			}
		}
		if (sum > l) cout << "NO" << endl;
	}
	return 0;
} 

3998. 變成1

題目連結:

https://www.acwing.com/problem/content/4001/

1. 題目描述

給定一個二進位制數 x,在它變為 1 之前,不斷對它進行如下操作:

  • 如果 x 為奇數,則將 x 加 1。
  • 如果 x 為偶數,則將 x 除以 2。

請問,多少次操作後,xx 會變為 11。

輸入格式

共一行,一個 01 字串,表示二進位制數 x。

輸出格式

一個整數,表示所需操作次數。

資料範圍

前六個測試點滿足,x 的位數不超過 11。
所有測試點滿足,x 的首位不為 0,且位數不超過 \(10^6\)

輸入樣例1:

1

輸出樣例1:

0

輸入樣例2:

1001001

輸出樣例2:

12

輸入樣例3:

101110

輸出樣例3:

8

2. 思路及題解

思路:

  • 由於x的位數整體不超過\(10^6\),即需要用字串(string)儲存
  • 對於二進位制字串,如何判斷二進位制奇偶數?
    • 看二進位制的最低位,如果最低位為0,二進位制位偶數;如果最低位為1,二進位制位偶數。
  • 如何對二進位制數進行加1除2操作?
    • 加1:從最低位開始,逢二進一。
    • 除2:二進位制右移一位,對於二進位制陣列,即二進位制字串長度減1即可。

題解:

#include <iostream>
#include <map>
#include <vector>
#include <utility>
#include <algorithm>
#include <cmath> 
#include <string>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long ll;

int main()
{
	string s;
	cin >> s;
	ll cnt = 0;
	ll end = s.size();
	while (end != 1)
	{
		cnt++;
        // 判斷二進位制最低位,如果為0,說明為偶數;如果為1說明為奇數
        // 若為偶數,x除以2,即二進位制數右移1位,轉化到字串上,就是end減1
        // 若為奇數,x加1,即從最低位開始加,逢二進一
		if (s[end - 1] == '0') end--;
		else
		{
			for (int i = end - 1; i >= 0; --i)
			{
				if (s[i] - '0' + 1 > 1) 
				{
					s[i] = '0';
				}
				else
				{
					s[i] = '1';
					break;
				}
			}
		}	
	}
    // 判斷如果s[0]為0,說明前面逢二進一時候,此時需要再做一次除2操作,即操作次數需要加1
	if (s[0] == '0')
		cout << cnt + 1 << endl;
	else
		cout << cnt << endl;
	return 0;
} 

3999. 最大公約數

題目連結:

https://www.acwing.com/problem/content/description/4002/

1. 題目描述

給定兩個正整數 a,m,其中 a<m。

請你計算,有多少個小於 m 的非負整數 x 滿足:

\[gcd(a,m)=gcd(a+x,m) \]

輸入格式

第一行包含整數 T,表示共有 T 組測試資料。

每組資料佔一行,包含兩個整數 a,m。

輸出格式

每組資料輸出一行結果,一個整數,表示滿足條件的非負整數 x 的個數。

資料範圍

前三個測試點滿足,1≤T≤10。
所有測試點滿足,1≤T≤50,\(1≤a<m≤10^{10}\)

輸入樣例:

3
4 9
5 10
42 9999999967

輸出樣例:

6
1
9999999966

2. 思路及題解

思路:

題解:


未完待續。。。