牛客周赛 Round 61
A-Letter Song
签到题
代码
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
char x;
cin >> a >> x >> b >> x >> c;
a += 10;
printf("%04d-%02d-%02d", a, b, c);
}
B-简单图形问题
思路
正方形面积:\(x^2\),正三角形面积:\(\frac{\sqrt{3}}{4} x^2\),判断一下能组成什么就行。
代码
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
int main()
{
int t;
cin >> t;
while (t --)
{
ll s;
cin >> s;
ll x = sqrt(s);
ll y = sqrt(4 * s / sqrt(3));
if (x * x == s && y * y * sqrt(3) / 4 == s) {
cout << 2 << '\n';
}
else if (x * x == s) {
cout << 0 << '\n';
}
else if (y * y * sqrt(3) / 4 == s) {
cout << 1 << '\n';
}
else cout << 3 << '\n';
}
return 0;
}
C-小红的差值构造
思路
根据给出的目标点(x, y),如果x>0,显然U操作数量一定要比x值大,否则就不可能到达,同理其他情况也一样。
接下来讨论可行的方案数,同样以x>0的情况讨论,假设用u记录一共有多少个U操作,且U操作一定要选满x个,那么我们就从选则x个开始增加选择的数量,同时也从0开始增加反方向D操作的数量,这样保证最终结果一定到达x。根据组合数概念,就有\(C_{u}^{x+i} * C_{d}^{i}\)搭配的方案数。其他情况同理。
代码
#include <iostream>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int M = 1e6;
int n, x, y;
string s;
ll fact[M + 10], infact[M + 10];
ll qmi(int a, int b)
{
ll res = 1;
while(b)
{
if(b & 1) res = res * a % mod;
a = (ll)a * a % mod;
b >>= 1;
}
return res;
}
void init()
{
fact[0] = infact[0] = 1;
for(int i = 1; i <= M; i ++) fact[i] = fact[i - 1] * i % mod;
infact[M] = qmi(fact[M], mod - 2);
for(int i = M - 1; i >= 1; i --) infact[i] = infact[i + 1] * (i + 1) % mod;
}
ll C(int a, int b)
{
if(b < 0 || a - b < 0) return 0;
return fact[a] * infact[b] % mod * infact[a - b] % mod;
}
void solve()
{
cin >> n >> x >> y;
cin >> s;
int l = 0, r = 0, d = 0, u = 0;
for (auto i : s)
{
if (i == 'L') l ++;
if (i == 'R') r ++;
if (i == 'D') d ++;
if (i == 'U') u ++;
}
int L = 0, R = 0, D = 0, U = 0;
if (x > 0) {
if (u < x) {
cout << "NO" << '\n';
return ;
}
U = x;
}
else if (x < 0) {
if (d < abs(x)) {
cout << "NO" << '\n';
return ;
}
D = abs(x);
}
if (y > 0) {
if (r < y) {
cout << "NO" << '\n';
return ;
}
R = y;
}
else if (y < 0) {
if (l < abs(y)) {
cout << "NO" << '\n';
return ;
}
L = abs(y);
}
cout << "YES" << ' ';
ll s1 = 0;
if (x >= 0) {
for (int i = 0; i <= min(u - U, d); i ++)
s1 = (s1 + C(u, U + i) * C(d, i) % mod) % mod;
}
else {
for (int i = 0; i <= min(d - D, u); i ++)
s1 = (s1 + C(d, D + i) * C(u, i) % mod) % mod;
}
ll s2 = 0;
if (y < 0) {
for (int i = 0; i <= min(l - L, r); i ++)
s2 = (s2 + C(l, L + i) * C(r, i) % mod) % mod;
}
else {
for (int i = 0; i <= min(r - R, l); i ++)
s2 = (s2 + C(r, R + i) * C(l, i) % mod) % mod;
}
for (int i = 0; i < n; i ++)
{
if (U && s[i] == 'U') {
cout << s[i];
U --;
}
if (D && s[i] == 'D') {
cout << s[i];
D --;
}
if (L && s[i] == 'L') {
cout << s[i];
L --;
}
if (R && s[i] == 'R') {
cout << s[i];
R --;
}
}
cout << ' ' << s1 * s2 % mod << '\n';
}
int main()
{
init();
int t;
cin >> t;
while (t --) solve();
return 0;
}
D-小红的差值构造
思路
根据题意,就是到x和y两个点的最短距离之和的最小值。分情况讨论一下,要么x和y都在1~n以内,要么一个在外面,一个在里面。很显然的,要贪最小,就是位置最中间的时候(证明不会),第一个情况,x为\(mid-\frac{l}{2}\)、y为\(mid+\frac{l}{2}\),第二个情况,x为mid、y为mid+l,取这两个值的最小值。
代码
#include <iostream>
using namespace std;
typedef long long ll;
int n, l;
ll s(ll x)
{
return x * (x + 1) / 2;
}
ll func(ll x)
{
if (x % 2) return s(x / 2 + 1) + s(x / 2);
else return s(x / 2) * 2;
}
void solve()
{
cin >> n >> l;
int mid = (n + 1) / 2;
int x = mid - l / 2, y = x + l;
ll res = s(x - 1) + s(n - y) + func(y - x - 1);
ll ans = func(n - 1);
if (ans < res) cout << mid << ' ' << mid + l << ' ' << ans << '\n';
else cout << x << ' ' << y << ' ' << res << '\n';
}
int main()
{
int t;
cin >> t;
while (t --) solve();
return 0;
}