洛谷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

posted @ 2020-11-29 21:31  追梦人1024  阅读(124)  评论(0编辑  收藏  举报