2022NOIPA层联测8
不看%%%Chen_jr的题解不会改题,看了又觉得啊我不用写了。。一下有一些内容来自【直接鹤】
于是先引个流,尽管我认为我的流量集合是他的真子集。。
问题 A: 【2022NOIP联测8 10月14日】tothecrazyones
当a < x + y 时,如果不存在 a >= x,张三就直接输了,否则张三赢当且仅当以下两个条件中有一个成立:
1. x <= y 张三随便选一堆能拿的石子拿掉,李四就被卡住了。
2. x > y,但不存在 i 满足 y <= ai < x 如果 y < x <= ai,张三作为先手一定会把这个ai 取了,李四又被卡住了。
考虑一般情况,如果先手/后手希望保持某个状态,那么对方选一个ai,自己可以跟着选这个ai,相当于给ai减去x + y,此时答案不变,于是就可以对x + y 取模。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 3;
const int N = 1e6 + 2;
const int inf = 2147483647;
int T, x, y, n, a[maxn];
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline bool check()
{
for(int i=1; i<=n; i++)
{
if(a[i] >= y && a[i] < x) return 0;
}
return 1;
}
inline bool judge()
{
for(int i=1; i<=n; i++)
{
if(a[i] >= x) return 1;
}
return 0;
}
int main()
{
T = read();
while(T--)
{
n = read(); x = read(); y = read();
for(int i=1; i<=n; i++)
{
a[i] = read(); a[i] %= (x+y);
}
if(!judge())
{
printf("0\n"); continue;
}
if(x <= y) printf("1\n");
else
{
if(check()) printf("1\n");
else printf("0\n");
}
}
return 0;
}
问题 B: 【2022NOIP联测8 10月14日】vmefifty
的确是考试原题,然而当时这场考试我只做了两个题。。难怪没有印象。。。
设 fi 表示前 i 个元素,删到只剩下一些与 ai 相等的元素,最多剩下多少个数,当 a[i] 与 a[j] 相同并且中间所有数都能删除时,f[i] = max(f[i], f[j]+1),一个区间能被完全删除的条件是长度为偶数并且不存在某个数出现次数大于区间长度的一半。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2007;
int T, n, a[maxn], f[maxn][maxn], dp[maxn];
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch^48);
ch = getchar();
}
return x * f;
}
int main()
{
T = read();
while(T--)
{
n = read();
for(int i=1; i<=n; i++) a[i] = read();
for(int i=1; i<=n; i++)
{
int m = 0;
vector<int> c(n+1);
c[a[i]]++; m = max(m, c[a[i]]);
for(int j=i+1; j<=n; j++)
{
c[a[j]]++; m = max(m, c[a[j]]);
int l = j-i;
if(l & 1 && m <= (l+1)/2) f[i][j] = 1;
else f[i][j] = 0;
}
}
for(int i=1; i<=n; i++)
{
if(i == 1 || f[1][i-1]) dp[i] = 1;
else dp[i] = 0;
}
for(int i=1; i<=n; i++)
{
for(int j=i+1; j<=n; j++)
{
if(dp[i] && a[j] == a[i] && (j==i+1 || f[i+1][j-1]))
{
dp[j] = max(dp[j], dp[i] + 1);
}
}
}
int ans = 0;
for(int i=1; i<=n; i++)
{
if(f[i+1][n] || i==n) ans = max(ans, dp[i]);
}
printf("%d\n", n-ans);
}
return 0;
}
问题 C: 【2022NOIP联测8 10月14日】wishusgoodluck
我的暴力只有24pts...
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
const int inf = 2147483647;
int n, m, s[maxn], ans = inf, d[maxn], res;
char c[maxn];
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch^48);
ch = getchar();
}
return x * f;
}
int count(int x)
{
int cnt = 0;
while(x)
{
x -= (x & -x);
cnt++;
}
return cnt;
}
int main()
{
n = read(); m = read();
for(int i=0; i<n; i++)
{
scanf("%s", c+1);
for(int j=1; j<=m; j++)
{
if(c[j] == '1') s[j] |= (1<<i);
}
}
int Max = 1 << n;
for(int i=0; i<Max; i++)
{
res = 0;
for(int j=1; j<=m; j++)
{
d[j] = s[j];
d[j] ^= i;
int cnt = count(d[j]);
if(cnt > n - cnt) cnt = n - cnt;
res += cnt;
if(res >= ans) break;
}
ans = min(ans, res);
}
printf("%d\n", ans);
return 0;
}
问题 D: 【2022NOIP联测8 10月14日】xiongaktenioi
刚才我完全鹤了一个居然T了!?原因是我把 j += i 鹤成了 j++。。。公式太多我比较无语,就不再打一遍了qwq
什么时候我能学会用好看的字体写公式啊……
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int mod = 1e9 + 7;
const int inf = 2147483647;
int n, a[maxn], fa[maxn], f[maxn], g[maxn], cnt[maxn];
ll si[maxn];
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch^48);
ch = getchar();
}
return x * f;
}
int main()
{
n = read();
for(int i=1; i<=n; i++) a[i] = read();
for(int i=2; i<=n; i++) fa[i] = read();
for(int i=n; i>=1; i--) {si[i] += a[i]; si[fa[i]] += si[i];}
for(int i=1; i<=n; i++)
{
ll now = si[1] / __gcd(si[i], si[1]);
if(now <= n) cnt[now]++;
}
for(int i=1; i<=n; i++) if(cnt[i])
{
for(int j=i; j<=n; j+=i)
{
f[j] += cnt[i];
}
}
for(int i=1; i<=n; i++) f[i] = f[i] == i;
for(int i=1; i<=n; i++) g[i] = f[i];
int ans = 1;
for(int i=2; i<=n; i++)
{
ans = (ans + g[i]) % mod;
for(int j=i+i; j<=n; j+=i) if(f[j]) g[j] = (g[j]+g[i])%mod;
}
printf("%d\n", ans);
return 0;
}
时光花火,水月星辰