0
点赞
收藏
分享

微信扫一扫

0218 模拟赛

DT_M 2023-02-21 阅读 25


T1

0218 模拟赛_#define

题解

先看看标算

0218 模拟赛_ci_02


代码超级短:

#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), i##_end_ = (b); i < i##_end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 110;

int n, K, l;

int main()
{
freopen("circle.in", "r", stdin);
freopen("circle.out", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d%d", &n, &K, &l);
int inv = -1;
REP(i, 1, n)
if (K * i % n == 1)
{
inv = i;
break;
}
if (~inv)
{
puts("YES");
REP(i, 0, l)
{
static int tmp[maxn + 5];
memset(tmp, 0, sizeof tmp);
REP(j, 0, K) tmp[(i + j) * inv % n] = 1;
REP(j, 0, n) printf("%d", tmp[j]);
printf("\n");
}
}
else puts("NO");
}
return 0;
}

我的想法是这样:

考虑把01序列变为记录每个1之前有多少个0的序列,这样序列长度从n变为k,然后对于新序列,A类型操作是要求序列循环同构,B类型操作相当于把某个数-1,它后面的数+1,然后如果执行了B操作之后还能执行A操作,说明序列元素差不会超过1.然后可以把所有元素减去n/k,然后变为01序列,变成了子问题.直接递归计算。

无解情况:gcd(n,k)!=1

整个算法相当于暴力枚举+递归。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
int a[MAXN][MAXN], l, b[MAXN];
void solve(int n, int k) {
if(k == 1) {
for(int i = 1; i <= l; ++i) a[i][i%n] = 1;
return;
}
solve(k, n % k);
int bs = n / k;
for(int i = 0; i < k; ++i) b[i] = a[1][i];
for(int now = 0, i = 0; i < k; ++i) {
for(int j = now; j < now+bs+b[i]; ++j)
a[1][j] = 0;
a[1][now+bs+b[i]-1] = 1;
now += bs+b[i];
}
for(int i = 2, tmp; i <= l; ++i) {
tmp = 0;
while(++tmp < n) {
for(int j = 0; j < n; ++j) a[i][j] = a[i-1][(j+tmp)%n];
int cnt = 0, p1 = 0, p2 = 0;
for(int j = 0; j < n; ++j) {
if(a[i][j] != a[i-1][j]) {
++cnt;
if(cnt == 1) p1 = j;
if(cnt == 2) p2 = j;
}
if(cnt > 2) break;
}
if(cnt == 2 && ((a[i][p1] == 0 && a[i][p2] == 1 && p2-p1 == 1) || (a[i][p1] == 1 && a[i][p2] == 0 && p1 == 0 && p2 == n-1))) break;
}
}
}
int n, k;
int main () {
freopen("circle.in", "r", stdin);
freopen("circle.out", "w", stdout);
int T; scanf("%d", &T);
while(T--) {
scanf("%d%d%d", &n, &k, &l);
if(__gcd(n, k) > 1) { puts("NO"); continue; }
memset(a, 0, sizeof a);
solve(n, k); puts("YES");
for(int i = 1; i <= l; puts(""), ++i)
for(int j = 0; j < n; ++j)
printf("%d", a[i][j]);
}
}

T2

0218 模拟赛_#define_03


直接上题解

0218 模拟赛_ci_04


就是按照最优前缀排序后贪心计算。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 55;
int n, p[MAXN], id[MAXN];
string s[MAXN], c[MAXN];
int fc(int i, int j) {
string a = c[i], b = c[j];
while(a.size() != b.size()) {
if(a.size() < b.size()) a = a + c[i];
else b = b + c[j];
}
return a < b ? -1 : b < a ? 1 : 0;
}
bool cmp(int i, int j) {
int tmp = fc(i, j);
return tmp ? tmp == -1 : s[i].substr(p[i])+'U' > s[j].substr(p[j])+'U';
}
int main () {
freopen("dna.in", "r", stdin);
freopen("dna.out", "w", stdout);
cin>>n;
for(int i = 1; i <= n; ++i) cin>>s[i];
for(int i = 1; i <= n; ++i) {
int len = s[i].size();
for(int j = 1; j <= len; ++j) {
bool flg = 1;
for(int k = j; k < len; ++k) {
if(s[i][k%j] < s[i][k]) { flg = 1; break; }
if(s[i][k%j] > s[i][k]) { flg = 0; break; }
}
if(flg) { c[i] = s[i].substr(0, j); break; }
}
if(!c[i].size()) c[i] = s[i];
int L = c[i].size();
for(int j = L; j < len; j += L)
if(c[i] != s[i].substr(j, L)) { p[i] = j; break; }
if(!p[i]) p[i] = len;
id[i] = i;
}
sort(id + 1, id + n + 1, cmp);
string mn, now, ans; ans = s[id[n]][0];
for(int i = n-1, j, len, p; i; --i) {
now = mn = s[id[i]][p=0] + ans;
len = s[id[i]].size();
for(j = 1; j < len; ++j) {
now = ans;
for(int k = j; k >= 0; --k) now = s[id[i]][k] + now;
if(now < mn) mn = now, p = j;
}
while(~p) ans = s[id[i]][p--] + ans;
}
cout<<ans<<endl;
}

T3

0218 模拟赛_#include_05


0218 模拟赛_#include_06


难点在于读题。

0218 模拟赛_#include_07

#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), i##_end_ = (b); i < i##_end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int __buffsize = 100000;
char __buff[__buffsize];
char *__buffs, *__buffe;

#define getc() (__buffs == __buffe ? fread(__buff, 1, __buffsize, stdin), __buffe = __buff + __buffsize, *((__buffs = __buff)++) : *(__buffs++))

template<typename T> inline T &Read(T &x)
{
static char c;
while (1)
{
c = getc();
if (c == '-' || (c >= '0' && c <= '9')) break;
}
bool flag = c == '-';
x = flag ? 0 : c - '0';
while (1)
{
c = getc();
if (c < '0' || c > '9') break;
(x *= 10) += c - '0';
}
if (flag) x = -x;
return x;
}

#undef getc

const int maxn = 200100;
const LL maxsum = 1e17;

int n;
vector<int> children[maxn + 5];
LL gain[maxn + 5];
LL loss[maxn + 5];
int fa[maxn + 5];

multiset<pair<LL, LL> > all[maxn + 5];

void dfs(int x)
{
for (auto y : children[x])
{
dfs(y);
if (SZ(all[y]) > SZ(all[x])) swap(all[x], all[y]);
for (auto u : all[y]) all[x].insert(u);
all[y].clear();
}
LL cur_invest = loss[x], cur_profit = gain[x] - loss[x];
while (!all[x].empty() && (cur_profit <= 0 || cur_invest + cur_profit >= all[x].begin()->x))
{
auto tmp = all[x].begin();
cur_invest += max(0ll, tmp->x - (cur_invest + cur_profit));
cur_profit += tmp->y;
all[x].erase(tmp);
}
if (cur_profit > 0) all[x].insert(mp(cur_invest, cur_profit));
}

int main()
{
freopen("prospecting.in", "r", stdin);
freopen("prospecting.out", "w", stdout);
Read(n);
loss[0] = maxsum;
REP(i, 1, n)
{
Read(fa[i]);
Read(gain[i]);
Read(loss[i]);
children[fa[i]].pb(i);
if (!~gain[i]) gain[i] = maxsum * 2;
}
dfs(0);
printf("%lld\n", all[0].begin()->x - maxsum);
return 0;
}


举报

相关推荐

0 条评论