A、九峰与签到题
使用set把过程中全部低于50通过率的题目统计一下就行了。
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
#define repp(i, sta, en) for(int i=sta; i>=en; --i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 7;
struct Node {
ll val;
int id;
bool operator < (const Node& opt) const {
return val < opt.val;
}
};
ll n, m;
int ac[N], sub[N];
void solve() {
js;
cin >> m >> n;
string s;
int id;
set<int> st;
while (m--) {
cin >> id >> s;
if (s == "AC") ++ac[id];
++sub[id];
if (!st.count(id) and ac[id] < (sub[id] + 1) / 2) st.insert(id);
}
if (st.size() == n) cout << "-1";
else {
rep(i, 1, n) {
if (st.count(i) == 0)
cout << i << " ";
}
}
}
int main() {
//int T = read(); while (T--)
solve();
return 0;
} J、邬澄瑶的公约数
发现我们要找到的全部数的,那么我们把全部的数分解质因数,拿到全部的因子。
我们知道数可以分成
我们使用两个计数器,分别统计在不同中质数
的出现次数,以及出现的幂次。那么如果一个质数一共出现 n 次我们才能在
中拿到这个质数,并且贡献就是出现幂次最小的哪个。
const int N = 1e4 + 7;
vector<int> prime;
bool vis[N];
void getprime() {
vis[1] = 1;
rep(i, 2, N - 1) {
if (!vis[i]) prime.push_back(i);
for (auto& it : prime) {
if (it * i >= N) break;
vis[it * i] = 1;
if (i % it == 0) break;
}
}
}
ll n, m;
ll x[N], p[N];
void solve() {
n = read();
rep(i, 1, n) x[i] = read();
rep(i, 1, n) p[i] = read();
map<int, ll> mp1, mp2;
rep(i, 1, n) {
ll tmp = x[i];
for (auto& it : prime) {
if (it > tmp) break;
if (tmp % it == 0) {
++mp1[it];
int cnt = 0;
while (tmp % it == 0)
++cnt, tmp /= it;
if (mp2.count(it)) mp2[it] = min(mp2[it], cnt * p[i] % MOD);
else mp2[it] = cnt * p[i] % MOD;
}
}
}
ll ans = 1;
for (auto& it : prime) {
if (!mp1.count(it)) continue;
if (mp1[it] != n) continue;
ans = ans * qpow(it, mp2[it], MOD) % MOD;
}
print(ans);
} B、武辰延的字符串
字符串匹配我们有hash办法做到。
那么对于给出的字符串S和T,我们枚举他们公共前缀,接下来还需要使用另一个S的前缀拼接到后面和T一致。比如我们看
aaab aabb 1、我们枚举第一个字符串就选a,那么接下来就要判断第二个字符串除掉a也就是剩下abb 和第一个字符串最长的匹配长度是多少,显然只能是1,因为a+a=a+a,a+aa!=a+ab 2、我们枚举第一个字符串选aa,接下来去找第二个字符串除掉aa剩下的和第一个字符串 的最长公共前缀,显然答案是0,因为只有aa=aa,aa+a!=aa+b 3、我们枚举第一个字符串选aaa,因为第二个字符串aab!=aaa,所以后面都不需要枚举了,直接退出即可
我们发现只需要判断长度,具有单调性,使用二分优化。时间复杂度就可以到。
当然如果你学会了exkmp,你会发现它就是干这个事的,它的next数组就是求得和前面串的最长公共前缀长度,直接累加一下就是答案了,时间复杂度可以优化到。
ll n, m;
char s1[N], s2[N];
ull has1[N], has2[N], p[N], bas = 131;
ull query1(int l, int r) {
return has1[r] - has1[l - 1] * p[r - l + 1];
}
ull query2(int l, int r) {
return has2[r] - has2[l - 1] * p[r - l + 1];
}
void solve() {
scanf("%s %s", s1 + 1, s2 + 1);
p[0] = 1;
rep(i, 1, N - 1) p[i] = p[i - 1] * bas;
n = strlen(s1 + 1);
m = strlen(s2 + 1);
rep(i, 1, n)
has1[i] = has1[i - 1] * bas + (s1[i] - 'a');
rep(i, 1, m)
has2[i] = has2[i - 1] * bas + (s2[i] - 'a');
ll ans = 0;
rep(i, 1, n) {
if (s1[i] != s2[i]) break;
int l = i + 1, r = m, res = 0;
while (l <= r) {
int mid = l + r >> 1;
ull a = query1(1, mid - i);
ull b = query2(i + 1, mid);
if (a == b) res = mid - i, l = mid + 1;
else r = mid - 1;
}
ans += res;
}
print(ans);
} G、九峰与蛇形填数
发现每次后面的会覆盖前面的,说明前面填的数后面又填了,那么前几次都是无用功。
那么我们从后往前遍历输入的填数顺序,使用一个数组记录答案,一个数组记录位置下一个没填的
在什么地方。这样就可以保证每个位置最多遍历一遍。复杂度有
const int N = 2000 + 7;
const int M = 3000 + 7;
ll n, m;
int s[N][N];
int l[N][N];
int p[4][M];
void solve() {
n = read(), m = read();
rep(i, 1, m)
rep(j, 1, 3) p[j][i] = read();
repp(i, m, 1) {
int sti = p[1][i], stj = p[2][i];
int edi = sti + p[3][i] - 1, edj = stj + p[3][i] - 1;
rep(j, sti, edi) {
rep(k, stj, edj) {
int x;
if ((j - sti) & 1) x = (j - sti + 1) * p[3][i] - (k - stj);
else
京公网安备 11010502036488号