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