文章目录
- 前言
- 说明
- 题解
- 1644.Euler YYDS![找规律]
- 1649.Palindrome of prime number[模拟 + 暴力判断质数]
- 1652.The Magic LMR Ring[找规律]
- 1654.Treasure House[BFS + 记录路径]
- 1653.The number of Invertion[逆序对模板题]
- 1647.L Sequence[模拟]
- 1648.Min. Min? Min![差分思想]
- 1656.Changing a Character[?]
- 1646.Extraordinary Permutation[单调栈 + 算贡献 + 费马小定理]
- 1651.Team A is better or Team B is better[DFS + 计算贡献]
- 1643.Balanced Number[数位DP + 三进制压缩]
- 1650.Perfect Sudoku[跳舞链 || 爆搜 + 剪枝]
- 吐槽
- END
前言
\quad 今天出了一坨锅,原因是出题组人手不够(没人验题…,求轻喷
说明
\quad 以下内容为现场赛时写的,一边看榜,一边写,所以是按照每道题被拿走FB的顺序写的。
题解
1644.Euler YYDS![找规律]
出题人:lhr \quad 验题人:ymf
\quad 全场最简单的题目,于 00:15:10 被 Visiter 拿走全场 First Blood!
题目大意
\quad T ( 1 ≤ T ≤ 10 ) T\;(1 \leq T \leq 10) T(1≤T≤10) 组数据,每组给一个整数 n ( 1 ≤ n ≤ 1 0 100 ) n\;(1 \leq n \leq 10^{100}) n(1≤n≤10100),问 φ ( n ) \varphi(n) φ(n) 的奇偶性.
分析
\quad 找规律可知:当 n ≥ 3 n \geq 3 n≥3 时 φ ( n ) \varphi(n) φ(n) 恒为偶数.
\quad 可使用更相减损之术: gcd ( x , n ) = g c d ( n − x , n ) \gcd(x, n) = gcd(n - x, n) gcd(x,n)=gcd(n−x,n) 简单证明.
代码实现
#include <bits/stdc++.h>
using namespace std;
const int M = (int)1e2;
char n[M + 5];
void work()
{
scanf("%s", n);
puts(strcmp(n, "1") == 0 || strcmp(n, "2") == 0 ? "odd" : "even");
}
int main()
{
// freopen("3.in", "r", stdin);
// freopen("3.out", "w", stdout);
int T; scanf("%d", &T);
while(T--) work();
return 0;
}
1649.Palindrome of prime number[模拟 + 暴力判断质数]
出题人:wx \quad 验题人:lhr
\quad 00:19:41 FB 诞生,By:18XiWenjuan
题目大意
T ( 1 ≤ T ≤ 1 0 5 ) T\;(1 \leq T \leq 10^5) T(1≤T≤105) 组数据,每组一个质数 n ( 1 ≤ n ≤ 1 0 5 ) n\;(1 \leq n \leq 10^5) n(1≤n≤105),问 n n n 的回文数是否是质数.
分析
\quad 直接模拟 + 暴力循环 $[1, \sqrt{n}] $ 判断,事实证明这样不会 TLE.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char n[20];
bool is_prime(ll n)
{
for(int i = 2; 1ll * i * i <= n; ++i)
{
if(n % i == 0) return 0;
}
return 1;
}
void work()
{
scanf("%s", n);
int len = strlen(n);
for(int i = len; i < 2 * len - 1; ++i) n[i] = n[2 * len - i - 2];
ll m = 0;
for(int i = 0; i < 2 * len - 1; ++i) m = m * 10 + n[i] - '0';
puts(is_prime(m) ? "prime" : "noprime");
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
int T; scanf("%d", &T);
while(T--) work();
return 0;
}
1652.The Magic LMR Ring[找规律]
出题人:lhr \quad 验题人:
\quad 00:57:30 FB 诞生,By:2019jiyi
题目大意
\quad 求解大小为 n n n,间隔为 1 1 1 的约瑟夫环.
分析
\quad 找规律可得
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
答案 | 1 | 1 | 3 | 1 | 3 | 5 | 7 | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 |
\quad 答案显然.
\quad 证明:
\qquad 记 f ( n ) f(n) f(n) 为大小为 n n n,间隔为 1 1 1 约瑟夫环的答案.
\qquad 当 n n n 为偶数时
\qquad 删完一圈后发现,答案为 2 f ( n / 2 ) − 1 2f(n / 2) - 1 2f(n/2)−1.
\qquad 当 n n n 为奇数时
\qquad 删完一圈后发现,答案为 2 f ( n / 2 ) + 1 2f(n / 2) + 1 2f(n/2)+1.
\qquad 分析到这里,使用递归即可 A C AC AC.
\qquad 剩下的部分留给读者自行证明.
代码实现
\quad 2019jiyiの代码
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
int main()
{
int t;
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
ll n;
scanf("%lld",&n);
ll x=2;
while(x<=n)
{
x*=2;
}
x/=2;
ll y=n-x;
if(y==0) cout << 1 << endl;
else cout << y*2+1 << endl;
}
return 0;
}
\quad 2020lihaoranの代码
#include <bits/stdc++.h>
using namespace std;
int f(int n)
{
if(n <= 2) return 1;
if(n & 1) return 2 * f(n / 2) + 1;
else return 2 * f(n / 2) - 1;
}
void work()
{
int n; scanf("%d", &n);
printf("%d\n", f(n));
}
int main()
{
int T; scanf("%d", &T);
while(T--) work();
return 0;
}
1654.Treasure House[BFS + 记录路径]
出题人:lhr \quad 验题人:
\quad 00:38:22 FB 诞生,By:19zhanglikun 。
题目大意
\quad 给一张 n × m n \times m n×m 的地图,$’$’$ 可走, ′ # ′ '\#' ′#′ 不可走,求从 ( 1 , 1 ) (1,1) (1,1) 点出发到 ( n , m ) (n,m) (n,m) 的最短路径,若最短路径不唯一求字典序最大的路径.
分析
\quad 模板题,无需分析.
代码实现
#include <bits/stdc++.h>
using namespace std;
int n, m;
char s[15][15];
int step[15][15];
int pre[15][15];
int dx[] = {0, 1, -1, 0};
int dy[] = {-1, 0, 0, 1};
struct node
{
int x, y;
node(int _x = 0, int _y = 0): x(_x), y(_y){}
};
queue<node> q;
void bfs(int x, int y)
{
memset(step, -1, sizeof(step));
memset(pre, -1, sizeof(pre));
step[x][y] = 0;
q.push(node(x, y));
node u, v;
while(!q.empty())
{
u = q.front(); q.pop();
if(u.x == n && u.y == m) return;
for(int i = 0; i < 4; ++i)
{
v.x = u.x + dx[i];
v.y = u.y + dy[i];
if(v.x < 1 || v.x > n || v.y < 1 || v.y > m) continue;
if(s[v.x][v.y] == '#' || ~step[v.x][v.y]) continue;
step[v.x][v.y] = step[u.x][u.y] + 1;
pre[v.x][v.y] = i;
q.push(v);
}
}
}
stack<char> st;
void work()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%s", s[i] + 1);
bfs(1, 1);
printf("%d\n", step[n][m]);
int x = n, y = m;
while(x != 1 || y != 1)
{
if(pre[x][y] == 0) st.push('W'), ++y;
else if(pre[x][y] == 1) st.push('S'), --x;
else if(pre[x][y] == 2) st.push('N'), ++x;
else if(pre[x][y] == 3) st.push('E'), --y;
}
while(!st.empty())
{
putchar(st.top());
st.pop();
}
printf("\n");
}
int main()
{
work();
return 0;
}
1653.The number of Invertion[逆序对模板题]
出题人:ryc \quad 验题人:lhr
\quad 再次被 18XiWenjuan 于 00:40:57 拿走 First Blood 。
题目大意
\quad 求逆序对.
分析
\quad 大一不会的可以趁这个机会学习一下.
\quad 大二不会的可以重修了.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (int)1e6;
const int mod = (int)1e8 + 7;
int n;
ll a[M + 5];
ll b[M + 5];
ll merge_sort(ll a[], int l, int r)
{
if(l >= r) return 0;
int mid = (l + r) >> 1; ll cnt = (merge_sort(a, l, mid) + merge_sort(a, mid + 1, r)) % mod;
int i = l, j = mid + 1, k = 0;
while(i <= mid && j <= r) if(a[i] <= a[j]) b[++k] = a[i++]; else b[++k] = a[j++], (cnt += mid - i + 1) %= mod;
while(i <= mid) b[++k] = a[i++];
while(j <= r) b[++k] = a[j++];
for(int i = l, j = 1; i <= r; ++i, ++j) a[i] = b[j];
return cnt;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
printf("%lld\n", merge_sort(a, 1, n));
return 0;
}
1647.L Sequence[模拟]
出题人:lhr \quad 验题人:ymf
\quad 01:40:05 又 被 19zhanglikun 拿走 FB 。
题目大意
\quad 无需多言.
分析
\quad 直接模拟.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int m;
ll f[100];
ll s[100];
int pw[20];
int cal(ll n)
{
int c = 0;
while(n)
{
++c;
n /= 10;
}
return c;
}
void init()
{
f[1] = f[2] = 1; s[1] = 1, s[2] = 2;
for(int i = 3; i <= 90; ++i)
{
f[i] = f[i - 2] + f[i - 1];
s[i] = s[i - 1] + cal(f[i]) * f[i];
if(s[i] > (int)1e9)
{
m = i;
break;
}
}
pw[0] = 1;
for(int i = 1; i <= 9; ++i) pw[i] = pw[i - 1] * 10;
}
void work()
{
int n; scanf("%d", &n);
int p = 1; while(s[p] < n) ++p;
n -= s[p - 1];
int len = cal(f[p]);
n = (n - 1) % len + 1;
printf("%d\n", f[p] / pw[len - n] % 10);
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
init();
int T; scanf("%d", &T);
while(T--) work();
return 0;
}
1648.Min. Min? Min![差分思想]
出题人:lhr \quad 验题人:
\quad 02:44:22 又 被 19zhanglikun 拿走 FB 。
题目大意
\quad 前缀取min + 后缀取min.
分析
\quad 看代码就懂了.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (int)1e6;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = (ll)1e9 + 7;
int n, m;
unsigned long long k1, k2;
ll a[M + 5];
ll d[3][M + 5];
inline unsigned long long read(const long long& l, const long long& r)
{
unsigned long long k3 = k1, k4 = k2;
k1 = k4;
k3 ^= k3<<23;
k2 = k3^k4^(k3>>17)^(k4>>26);
return (k2 + k4) % (r - l + 1) + l;
}
void work()
{
scanf("%d %d %llu %llu", &n, &m, &k1, &k2);
for(int i = 1; i <= n; ++i)
{
a[i] = read(1ll, (ll)1e18);
d[1][i] = d[2][i] = inf;
}
int op, p; ll x;
while(m--)
{
op = read(1, 2); p = read(1, n); x = read(1ll, (ll)1e18);
d[op][p] = min(d[op][p], x);
}
for(int i = n - 1; i >= 1; --i) d[1][i] = min(d[1][i], d[1][i + 1]);
for(int i = 2; i <= n; ++i) d[2][i] = min(d[2][i], d[2][i - 1]);
for(int i = 1; i <= n; ++i) a[i] = min(a[i], min(d[1][i], d[2][i]));
ll ans = 0;
for(int i = 1; i <= n; ++i) ans = (ans + a[i]) % mod;
printf("%lld\n", ans);
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
return 0;
}
1656.Changing a Character[?]
出题人:? \quad 验题人:?
题目大意
\quad ?
分析
\quad ?
代码实现
\quad ?
1646.Extraordinary Permutation[单调栈 + 算贡献 + 费马小定理]
出题人:lhr \quad 验题人:
03:24:50 又又 被 19zhanglikun 拿走 FB 。
题目大意
\quad 给一个排列 P P P,求 P P P 所有总区间最大值除以最小值的乘积,答案对 998244353 998244353 998244353 取模.
分析
\quad 计算每个值当最大值和最小值的贡献.
\quad 单调栈维护每个数的最大值和最小值区间.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (int)1e5;
const ll mod = (ll)998244353;
int n, p[M + 5];
int st[M + 5], tp;
int L[M + 5], R[M + 5];
ll quick(ll a, ll b, ll p = mod)
{
a %= p;
ll s = 1;
while(b)
{
if(b & 1) s = s * a % p;
a = a * a % p;
b >>= 1;
}
return s % p;
}
ll inv(ll n, ll p = mod)
{
return quick(n, p - 2, p);
}
void work()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", &p[i]);
ll ans = 1;
/** 计算 Min 的贡献 **/
tp = 0;
for(int i = 1; i <= n; ++i)
{
while(tp && p[st[tp]] > p[i]) --tp;
if(tp) L[i] = st[tp] + 1;
else L[i] = 1;
st[++tp] = i;
}
tp = 0;
for(int i = n; i >= 1; --i)
{
while(tp && p[st[tp]] > p[i]) --tp;
if(tp) R[i] = st[tp] - 1;
else R[i] = n;
st[++tp] = i;
}
for(int i = 1; i <= n; ++i)
{
ans = ans * quick(p[i], 1ll * (i - L[i] + 1) * (R[i] - i + 1)) % mod;
assert(0 <= ans && ans < mod);
}
/** 计算 Max 的贡献 **/
tp = 0;
for(int i = 1; i <= n; ++i)
{
while(tp && p[st[tp]] < p[i]) --tp;
if(tp) L[i] = st[tp] + 1;
else L[i] = 1;
st[++tp] = i;
}
tp = 0;
for(int i = n; i >= 1; --i)
{
while(tp && p[st[tp]] < p[i]) --tp;
if(tp) R[i] = st[tp] - 1;
else R[i] = n;
st[++tp] = i;
}
for(int i = 1; i <= n; ++i)
{
ans = ans * inv(quick(p[i], 1ll * (i - L[i] + 1) * (R[i] - i + 1))) % mod;
assert(0 <= ans && ans < mod);
}
assert(0 <= ans && ans < mod);
printf("%lld\n", ans);
}
int main()
{
// freopen("input.txt", "r", stdin);
work();
return 0;
}
1651.Team A is better or Team B is better[DFS + 计算贡献]
出题人:ymf \quad 验题人:lhr
04:18:41 又又又 被 19zhanglikun 拿走 FB 。
题目大意
\quad 有 2 n 2n 2n 个人,每对人之间有一个攻击值,要求你给这 2 n 2n 2n 个人两两分组使得两组的攻击值最大.
分析
\quad D F S DFS DFS 暴搜,在搜索的过程中计算贡献.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int g[30][30];
int a[30], alen;
int b[30], blen;
ll mx;
void dfs(int u, int alen, int blen, ll s)
{
if(u == n + 1)
{
mx = max(mx, s);
return;
}
if(alen < n / 2)
{
a[alen + 1] = u;
ll t = s;
for(int i = 1; i <= blen; ++i) t += g[u][b[i]];
dfs(u + 1, alen + 1, blen, t);
}
if(blen < n / 2)
{
b[blen + 1] = u;
ll t = s;
for(int i = 1; i <= alen; ++i) t += g[a[i]][u];
dfs(u + 1, alen, blen + 1, t);
}
}
void work()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
scanf("%d", &g[i][j]);
dfs(1, 0, 0, 0);
printf("%lld\n", mx);
}
int main()
{
work();
return 0;
}
1643.Balanced Number[数位DP + 三进制压缩]
出题人:ryc \quad 验题人:lhr
题目大意
\quad 求区间 [ A , B ] [A, B] [A,B] 中有多少个数,数位上有偶数个偶数,奇数个奇数.
分析
\quad 大二的估计一看涉及知识就懂了.
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int num[20];
ll f[20][60000];
bool check(int n)
{
if(n == 0) return 0;
for(int i = 9, t; i >= 0; --i)
{
t = n % 3;
if((i&1) && t == 2 || !(i&1) && t == 1) return 0;
n /= 3;
}
return 1;
}
int cal_state(int cur, int x)
{
int num[10];
for(int i = 9; i >= 0; --i)
{
num[i] = cur % 3;
cur /= 3;
}
if(num[x] == 0) num[x] = 1;
else if(num[x] == 1) num[x] = 2;
else if(num[x] == 2) num[x] = 1;
cur = 0;
for(int i = 0; i <= 9; ++i) cur = cur * 3 + num[i];
return cur;
}
ll dfs(int pos, int state, bool leading, bool limit)
{
if(pos == -1) return check(state);
if(!limit && ~f[pos][state]) return f[pos][state];
ll res = 0; int up = (limit ? num[pos] : 9);
for(int i = 0; i <= up; ++i)
{
res += dfs(pos - 1, leading && i == 0 ? 0 : cal_state(state, i),
leading && i == 0, limit && i == up);
}
if(!limit) f[pos][state] = res;
return res;
}
ll cal(ll n)
{
if(n == 0) return 0;
int pos = 0;
while(n)
{
num[pos++] = n % 10;
n /= 10;
}
return dfs(pos - 1, 0, 1, 1);
}
void work()
{
ll l, r; scanf("%lld %lld", &l, &r);
printf("%lld\n", cal(r) - cal(l - 1));
}
int main()
{
memset(f, -1, sizeof(f));
int T; scanf("%d", &T);
while(T--) work();
return 0;
}
1650.Perfect Sudoku[跳舞链 || 爆搜 + 剪枝]
出题人:syh \quad 验题人:lhr、ymf
题目大意
\quad 问 2 2 2 阶数独有多少种状态答案唯一.
分析
\quad 俺只会爆搜…
代码实现
\quad 代码就不贴了.
吐槽
-
1002题 1 ≤ n ≤ 1 0 100 1 \leq n \leq 10^{100} 1≤n≤10100,居然还有人暴力枚举,头真铁啊!
-
暴躁老哥上线
END
所以说,知道自己的真实实力最重要,不要因为一时的失败就觉得自己不行。
一定要多试几次你才会知道,自己真的不行。