数学和细节题十分不行的我,这场被打懵了。wa到自闭。
A
因为对两个数字求 l c m lcm lcm,至少需要小的数字乘以二。所以我们针对每个区间端点,乘以二,判断是否在内即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int T;
int l, r;
int main()
{
T = read();
while (T--)
{
l = read(), r = read();
if (r < 2 * l) { printf("%d %d\n", -1 ,-1); }
else {
printf("%d %d\n", l, 2 * l);
}
}
return 0;
}
B
由题意,一共可以走k步,每次回头只能走一步,那么我们可以发现,每一次回头一共就有了2次步数的减少(去+回),再加上题目按时回头走的次数不多于五次,所以我们枚举回头次数。
针对一共 i i i次回头,我们最远能走到 k − 2 ∗ i 。 k-2*i。 k−2∗i。
我们只需要找到最大的 a [ i ] + a [ i + 1 ] a[i]+a[i+1] a[i]+a[i+1],使得这个循环走 i i i次即可。
其次,针对端点,可以考虑成从端点到端点+1, a [ n ] + a [ n + 1 ] a[n]+a[n+1] a[n]+a[n+1],这个循环走 i i i次。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e5 + 10;
int T, n, k, z;
int a[N];
int main()
{
T = read();
while (T--)
{
n = read(), k = read(), z = read();
upd(i, 1, n)a[i] = read();
int ans = 0;
upd(j, 0, z)
{
int len = k - 2 * j + 1;
int mx = 0;
int sum = 0;
upd(i, 1, len)
{
mx = max(mx, a[i] + a[i + 1]);
sum += a[i];
}
//sum += a[len];
ans = max(ans, sum + j * mx);
}
printf("%d\n", ans);
}
}
C
依题意,最后剩下的字符串一定形如 a b a b a b a b abababab abababab且长度是偶数。
所以暴力枚举我们剩余的两个数字即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int T, n;
char s[N];
int num[2];
int main()
{
T = read();
while (T--)
{
scanf("%s", s + 1);
n = strlen(s + 1);
int ans = INF;
upd(a, 0, 9)
{
upd(b, 0, 9)
{
num[0] = a, num[1] = b;
int now = 0;
int sum = 0;
upd(i, 1, n)
{
if (num[now] != s[i]-'0')sum++;
else {
now ^= 1;
}
}
if (now == 1) {
if (a != b)sum++;
}
ans = min(ans, sum);
}
}
printf("%d\n", ans);
}
return 0;
}
D
分为两个情况,第一个相交,第二个是不相交。
相交的话,先判断相交的长度是否大于 k k k,小于了直接输出0。大于的话,接着判断。我们可以发现,对于一组木板,我们将他扩展 L = m i n ( a l , b l ) L=min(a_l,b_l) L=min(al,bl), R = m a x ( a r , b r ) R=max(a_r,b_r) R=max(ar,br),是最优秀的。因为这样可以节省费用,同样是长度 R − L R-L R−L,分别扩展两个木板利用了自己的长度部分,使得费用是最少的。所以我们计算长度 R − L R-L R−L和 n ∗ ( R − L ) n*(R-L) n∗(R−L),判断与k的关系,不行的话利用两倍费用暴力扩展即可。
当不相交,首先扩展木板到相同的长度,然后判断他的 k k k的关系,如果 k k k更小的话,我们需要判断费用是否更加优秀。
有 a l , a r , b l , b r a_l,a_r,b_l,b_r al,ar,bl,br,我们假定a木板是更靠左的木板。有 a r < b l a_r
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<ll, ll> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int T;
ll n, k;
pir a, b;
ll judge(pir x, pir y)
{
return min(y.second, x.second) - max(x.first, y.first);
}
int main()
{
T = read();
while (T--)
{
n = read(), k = read();
ll ans = 0;
a.first = read(); a.second = read();
b.first = read(), b.second = read();
ll tp = judge(a, b);
if(tp>=0)
{
if (tp*n >= k) {
ans = 0;
}
else {
k -= tp * n;
int mod = (max(a.second, b.second) - min(a.first, b.first)) - tp;
if (mod*n >= k)
{
ans += k;
}
else {
ans += mod * n + (k - mod * n) * 2;
}
}
}
else {
if (a.first > b.first)swap(a, b);
int mx = max(a.second, b.second); int mn = min(a.first, b.first);
int mod = (mx - a.second) + (a.first - mn) + (mx - b.second) + (b.first - mn);
int len = mx - mn;
int dist = max(b.first, a.second) - min(b.first, a.second);
if (k <= len)ans += dist + k;
else {
int cnt = 0;
upd(i, 1, n) {
if (k >= len) {
k -= len; ans += mod;
cnt++;
}
else break;
}
{
if (cnt == n) {
ans += k * 2;
}
else {
if (dist > k)ans += 2 * k;
else ans += 2 * dist + (k - dist);
}
}
}
}
printf("%lld\n", ans);
}
return 0;
}
E
由,第x个月第y天和第y个月第x天是相同的星期几,我们可以得到:
( x − 1 ) ∗ d + y m o d w = = 0 (x-1)*d+y\mod w==0 (x−1)∗d+ymodw==0, ( y − 1 ) ∗ d + x m o d w = = 0 (y-1)*d+x \mod w==0 (y−1)∗d+xmodw==0,两式相减,就有:
( x − y ) ∗ ( d − 1 ) m o d w = = 0 (x-y)*(d-1)\mod w==0 (x−y)∗(d−1)modw==0因为 ( d − 1 ) (d-1) (d−1)是常数,将 d − 1 d-1 d−1除掉。就有:
( x − y ) m o d ( w / g c d ( w , ( d − 1 ) ) = = 0 (x-y)\mod (w/gcd(w,(d-1))==0 (x−y)mod(w/gcd(w,(d−1))==0,因为 x < = d & x < = m x<=d\&x<=m x<=d&x<=m同理可得 y y y,
故题目化简成求,有多少对 ( x , y ) (x,y) (x,y)满足上式。枚举倍数 w ′ ′ w'' w′′,即 x − y = = w ′ x-y==w' x−y==w′,针对 d m = m i n ( d , m ) dm=min(d,m) dm=min(d,m)而言,一共有 ∑ i = 1 d m / w ′ d m − w ′ ∗ i \sum_{i=1}^{dm/w'}dm-w'*i ∑i=1dm/w′dm−w′∗i,用通项公式化简即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#includem
#include
#include
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int T;
ll m, d, w;
ll gcd(ll a, ll b)
{
return a ? gcd(b%a, a) : b;
}
int main()
{
T = read();
while (T--)
{
m = read(), d = read(), w = read();
ll md = min(m, d);
ll w_ = w / gcd(w, d - 1);
ll cnt = md / w_;
ll ans = 0;
ans = md * cnt - w_ * (cnt*(cnt + 1) / 2);
printf("%lld\n", ans);
}
return 0;
}
F
考虑一个二分图(依靠颜色分为两种),我们如果正向连边,即颜色=1的点,向所有满足题意的颜色=2的点连边,该题不容易找到解法。反过来,如果颜色=1的向所以形成bad的颜色=2的点连边,那么题目就变成找到最大独立集。由网络流可以知道,最大独立集=n-最大匹配。故现在我们需要找到一个匹配方式,是最大的。
常规匹配变数可能是 n 2 n^2 n2,我们需要找到一个更优秀的方法。容易想到,利用扫描线的思想,我们把每一个线段抽象成两个点,起点和终点。现在开两个集合,表示颜色1,颜色2。针对每一个起点,我们添加他的终点进入集合,针对每一个终点,我们匹配另外一个集合中,最小的终点。可以容易的发现这样贪心的正确性。(利用multiset,不然会wa4,终点多个重合的情况)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int L[N], R[N], t[N];
int n;
struct node {
int a, b, c;
};
multiset<int>s[3];
vector<node>vec;
int main()
{
n = read();
upd(i, 1, n) {
L[i] = read(), R[i] = read(), t[i] = read(); t[i]--;
}
upd(i, 1, n)
{
vec.push_back(node{ L[i],i,0 });
vec.push_back(node{ R[i],i,1 });
}
sort(vec.begin(), vec.end(), [](node t1, node t2) {
if (t1.a == t2.a)
{
return t1.c < t2.c;
}
else { return t1.a < t2.a; };
});
int pi = 0;
for (auto k : vec)
{
int id = k.b;
int col = t[id];
if (k.c == 1)
{
if (s[col].find(R[id]) != s[col].end())
{
if (s[col^1].size()) {
pi++; s[col ^ 1].erase(s[col ^ 1].begin());
}
s[col].erase(s[col].find(R[id]));
}
}
else {
s[col].insert(R[id]);
}
}
cout << n - pi << endl;
return 0;
}