1. 程式人生 > 實用技巧 >洛谷11月月賽Ⅱ-div.2

洛谷11月月賽Ⅱ-div.2

目錄

洛谷11月月賽Ⅱ-div.2

寫在前面

終於碰到一場好做一丟丟的月賽了,qwq

前兩題還是可做的,第三題要億點點數學思維,第四題,互動題?(我又可以少做一道題了,哈哈哈)

A 雙生獨白

極限入門大水題

寫的有點麻煩,其實直接上switch即可

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
	getchar();
	putchar('#');
	for(int i = 1 ; i <= 3 ; i++) {
		int x = 0;
		char c = getchar();
		if(c >= 'A' && c <= 'F')
			x = 10 + c - 'A';
		else
			x = c - '0';
		x <<= 4;
		
		c = getchar();
		if(c >= 'A' && c <= 'F')
			x += 10 + c - 'A';
		else
			x += c - '0';
		
		x = 255 - x;
		int tmp = x >> 4;
		if(tmp < 10)cout << tmp;
		else	putchar(tmp - 10 + 'A');
		
		tmp = x & ((1 << 4) - 1);
		if(tmp < 10)cout << tmp;
		else	putchar(tmp - 10 + 'A');
	}
	return 0;
}

B 天選之人

卡評測機的萬惡之源!!!

其實不難,但是一開始寫得太麻煩了,寫了一堆特判,偷窺借鑑了大佬的程式碼後……

%#@¥……%¥……%&

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
inline ll minn(ll x , ll y) {
	return x < y ? x : y;
}
ll n , m , p , k;
ll x[100010] , y[100010];
int main() {
	cin >> n >> m >> k >> p;
	
	ll a = k / p;
	if(a > m) a = m;
	
	for(int i = 1 ; i <= p ; i++)
		x[i] = a , y[i] = m - a , k -= a;
	
	for(int i = p + 1 ; i <= n ; i++)
		x[i] = minn(k , a - 1) , y[i] = m - x[i] , k-= x[i];
	
	if(k > 0)puts("NO");
	else {
		puts("YES");
		for(int i = 1 ; i <= n ; i++)
			printf("%d %d\n" , x[i] , y[i]);
	}
	return 0;
}

C 移花接木

思路

分三種情況(注意下列式子中省略取模運算):

\(a=b\):

​ 很顯然,第h+1層的點全部刪除即可,答案為\(a^{h+1}\)

\(a>b\):

​ 當b=1時,不能使用等比數列,答案為\((a-1)^h+a\)

​ 否則,我們需要不斷使用“移花”操作即可,具體地,先不考慮最底層,第0層不用刪,第一層需進行\(b^0\cdot (a-b)\),第二層需進行\(b^1\cdot (a-b)\),以此類推,最後得到:

\[\begin{aligned} & b^0\cdot (a-b)+b^1\cdot (a-b)+b^2\cdot (a-b)+\cdots+b^{h-1}(a-b)\\ =&(a-b)(b^0+b^1+b^2+\cdots+b^{h-1})\\ =&\frac{b^h-1}{b-1} \end{aligned} \]

​ 上面用到等比數列知識,這裡不做贅述,請自行查閱資料,另外,由於除法運算不能直接取模,需要用到逆元,也請自行查詢資料

​ 最後,我們還要把最底層的子節點砍掉,運算元為:\(a\cdot b^h\)

\(a<b\):

​ 也很好操作但不是很好理解的一種情況,聽說是直接把最底層將要砍掉的節點直接移到上面,現在還不是很理解,運算元為\(a\cdot b^h\)

程式碼

AC程式碼

#include <iostream>
#include <cstdio>
#define ll long long
#define mod 1000000007ll
using namespace std;
ll read() {
	ll re = 0;
	char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0',
		c = getchar();
	return re;
}
ll pow_(ll x , ll p) {
	ll res = 1;
	ll mul = x;
	while(p != 0) {
		if(p & 1)
			res = (res * mul) % mod;
		mul = mul * mul % mod;
		p >>= 1;
	}
	return res % mod;
}
int main() {
	ll t = read();
	while(t--) {
		ll h , a , b;
		a = read() , b = read() , h = read(); 
		if(a == b)
			printf("%lld\n" , pow_(a , h + 1));
		else if(a > b)
			printf("%lld\n" , b == 1 ? ((a - 1) * h + a) % mod : ((pow_(b , h) - 1) % mod * pow_(b - 1 , mod - 2) % mod * (a - b) % mod + a * pow_(b , h) % mod) % mod);
		else
			printf("%lld\n" , pow_(b , h) * a % mod);
			
	}
	return 0;
}

資料生成

這裡採用輸入的方式獲得種子,詳見https://www.cnblogs.com/dream1024/p/14051523.html中的對拍程式

#include <bits/stdc++.h>
using namespace std;
int random(int r , int l = 1) {
	return l == r ? l : (long long)rand() * rand() % (r - l) + l;
}
int main() {
	unsigned seed;
	cin >> seed;//輸入種子
	seed *= time(0);
	srand(seed);
	
	int t = random(1000000);
	printf("%d\n" , t);
	for(int i = 1 ; i <= t ; i++) {
		int a = random(1e9) , b = random(1e9) , h = random(1e9);
		printf("%d %d %d\n" , a , b , h);
	}
	return 0;
}

D 滴水不漏

qwq