A. 解开束缚缠丝Ⅱ
回文串中至多出现一种字母是奇数个。
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n; cin >> n;
map<char,int> st;
int res = 0 , f = 0;
for( char c ; n ; n -- )
cin >> c , st[c] ++;
for( auto [k , v] : st ){
res += v;
if( v % 2 == 1 ) f = 1 , res --;
}
cout << res + f << "\n";
}
int32_t main() {
ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
int t ; cin >> t;
while( t -- ) solve();
return 0;
}
B. 7 的意志
计算前缀和,枚举左端点,二分右端点,复杂度\(O(n\log n)\)
#include<bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x;
}
void solve(){
int n = read();
vector<int> a(n+1);
for( int i = 1 ; i <= n ; i ++ ) a[i] = read() + a[i-1];
auto search = [a,n]( int st ){
int l = st , r = n , ans = n , mid ;
while(l <= r){
mid = (l + r) >> 1;
if( a[mid] - a[st-1] >= 7777 ) ans = mid , r = mid - 1;
else l = mid + 1;
}
return ans;
};
int res = 0;
for( int i = 1 , j ; i <= n ; i ++ ){
j = search(i);
res += ( a[j] - a[i-1] == 7777 );
}
printf("%d\n" , res);
}
int32_t main() {
for( int t = read() ; t ; t -- ) solve();
return 0;
}
C. 迷宫的十字路口
数量不多直接模拟就好。
用结构体存储每一次操作后的状态。结构题中包含位置,获得物品数量,轴上物品的位置。
操作1,就是移动,暴力统计移动过程中能拿哪些物品即可。
操作2,对轴上所有的点取相反数即可
操作3,交换x,y轴就好
操作4,回到\(T-1\)次操作后的状态即可
注意,即使位置没有移动也可能会获得物品
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
struct state {
int x, y, sum;
vector<int> X, Y;
state(const vector<pair<int, int>> &s) {
x = y = sum = 0;
for (auto [r, c]: s) {
if (r == 0) Y.push_back(c);
if (c == 0) X.push_back(r);
}
sort(X.begin(), X.end()), sort(Y.begin(), Y.end());
}
void op1(char op, int t) {
if ((op == 'X' && (x + t) * y != 0) || (op == 'Y' && x * (y + t) != 0)) return x = y = 0, void();
if (op == 'X') {
vector<int> cur;
int l = min(x, x + t), r = max(x, x + t);
for (auto i: X)
if (i >= l && i <= r) cur.push_back(i);
for (auto i: cur)
X.erase(lower_bound(X.begin(), X.end(), i));
sum += cur.size(), x += t;
} else {
vector<int> cur;
int l = min(y, y + t), r = max(y, y + t);
for (auto i: Y) if (i >= l && i <= r) cur.push_back(i);
for (auto i: cur)
Y.erase(lower_bound(Y.begin(), Y.end(), i));
sum += cur.size(), y += t;
}
return;
}
void op2(char op) {
if (op == 'X') {
for (auto &i: X) i = -i;
sort(X.begin(), X.end());
} else {
for (auto &i: Y) i = -i;
sort(Y.begin(), Y.end());
}
op1('X', 0), op1('Y', 0);
return;
}
void op3() {
swap(X, Y);
op1('X', 0), op1('Y', 0);
return;
}
};
int32_t main() {
int n = read();
vector<pair<int, int>> a(n);
for (auto &[x, y]: a) x = read(), y = read();
state now(a);
vector<state> T;
T.push_back(now);
char s[2];
for (int i = 1, m = read(), op, t; i <= m; i++) {
op = read();
if (op == 1) {
scanf("%s", s), t = read();
now.op1(s[0], t);
} else if (op == 2) {
scanf("%s", s);
now.op2(s[0]);
} else if (op == 3) {
now.op3();
} else if (op == 4) {
t = read();
if (t != i) now = T[t - 1];
}
T.push_back(now);
}
cout << now.sum << "\n";
return 0;
}
D. 转动命运之轮
要构造转动\(c\)轮的序列\(w_i\),即如果把传递当成是一个有向图的话,则图中最大的环的大小就是\(c\)
可以枚举每个人\(k\)所在环的大小\(c_k\),如果环的大小是\(i\),则还要从剩下\(n-1\)个人中选出\(i-1\)个,有\(C_{n-1}^{k-1}\)中情况,环上的排序情况是\((i-1)!\),环外的排序情况是\((n-i)!\),所以\(k\)所产生的贡献就是\(h_k\times \sum_{i=1}^n C_{n-1}^{k-1} (n-i)!(i-1)!\),所以整体的答案就是
\[\sum_{k=1}^{n} [ h_k\times \sum_{i=1}^n C_{n-1}^{k-1} (n-i)!(i-1)!]=\sum_{k=1}^{n} h_k\times \sum_{i=1}^n C_{n-1}^{k-1} (n-i)!(i-1)! \]#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2005, mod = 998244353;
int fact[N], invFact[N];
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int power(int x, int y) {
int ans = 1;
x = x % mod;
while (y) {
if (y & 1) ans = ans * x % mod;
y >>= 1, x = x * x % mod;
}
return ans;
}
int inv(int x) {
return power(x, mod - 2);
}
int C(int x, int y) { // x 中选 y 个
return fact[x] * invFact[x - y] % mod * invFact[y] % mod;
}
void init() {
fact[0] = 1, invFact[0] = inv(1);
for (int i = 1; i < N; i++)
fact[i] = fact[i - 1] * i % mod, invFact[i] = inv(fact[i]);
}
int32_t main() {
init();
int n = read(), res = 0;
for (int i = 1, x; i <= n; i++)
x = read(), res = (res + x) % mod;
int ans = 0;
for (int i = 1, t; i <= n; i++) {
t = C(n - 1, i - 1) * fact[i] % mod * fact[n - i] % mod;
ans = (ans + t) % mod;
}
cout << res * ans % mod;
return 0;
}
赛后发现了Note中的最后一句话
在本题中,可以理解为对所有满足 \(P\in U_n\)的集合 \(P\) 进行求和。
所以当\(c_k\)确定时有\((n-1)!\)中情况,所以对于\(k\)的答案是\(h_k\sum_{i=1}^{n}i(n-1)!=h_k\frac{n(1+n)}{2}(n-1)!=\frac{1}{2}h_k(n+1)!\)
漏掉提示真尴尬。。。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2005, mod = 998244353;
int fact[N], invFact[N];
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int n = read() , ans = 0 , res = 1;
for( int i = 1 ; i <= n ; i ++ )
ans = ( ans + read() ) % mod ;
for( int i = 3 ; i <= n+1 ; i ++ )
res = ( res * i ) % mod;
cout << ans * res % mod;
return 0;
}
E. 计算最小值
显然差值之和最小,最简单的方法是按照大小顺序取,例如\(\{1,2,3,4,5\}=|2-1|+|3-2|+|4-3|+|5-4|=5-1\),所以就是区间中的\(\max-\min\),这里要注意的是区间内必须包含\(n\)种,所以把所有的数字放在一起,同时记录属于哪一种,按照大小排序,最后用双指针算法做一下就好
#include<bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x;
}
int32_t main() {
int n = read() , m = read();
vector< pair<int,int> > v;
vector<int> cnt(n+1);
for( int i = 1 ; i <= n ; i ++ )
for( int j = m , x ; j ; j -- )
x = read() , v.emplace_back( x , i );
sort( v.begin(), v.end());
int res = INT_MAX;
for( int l = 0 , r = -1 ; l < v.size() ; l ++ ){
while( r+1 < v.size() && cnt[0] != n ){
r ++ , cnt[ v[r].second ] ++;
if( cnt[ v[r].second ] == 1 ) cnt[0]++;
}
if( cnt[0] != n ) break;
if( v[l].second != v[r].second ) res = min( res , v[r].first - v[l].first );
cnt[ v[l].second ]--;
if( cnt[v[l].second] == 0 ) cnt[0] --;
}
cout << res << "\n";
return 0;
}
F. 月光奏鸣曲
模拟题,预处理选旋转90,180,270度的情况,旋转270就是反方向旋转90,然后按照题目要求比较就好。推荐用vector
因为可以直接用==
比较
#include<bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x;
}
void f( const int & n , const vector<vector<int>> & a , vector<vector<int>> & b ){
for( int i = 0 ; i < n ; i ++ )
for( int j = 0 , l = n-1 ; j < n ; j ++ , l -- )
b[i][j] = a[l][i];
return;
}
void solve(){
int n = read();
vector< vector<int> > a( n , vector<int>(n));
auto b = a , c = a , d = a , e = a;
for( auto &it : a )
for( auto &i : it ) i = read();
for( auto &it : b )
for( auto &i : it ) i = read();
f(n, a, c), f(n, c, d) , f(n, d, e);
if( a == b ) printf("0\n");
else if( c == b || e == b ) printf("1\n");
else if( d == b ) printf("2\n");
else printf("-1\n");
return;
}
int32_t main() {
for( int t = read() ; t ; t -- ) solve();
return 0;
}
G. 电子表校对
模拟题,先处理出所有数字的表示方式,然后转换两个时间,先把时间都转换成秒,然后再比较
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef array<string, 3> num;
const num s[10] = {
{" _ ", "| |", "|_|",},
{" ", " |", " |",},
{" _ ", " _|", "|_ ",},
{" _ ", " _|", " _|",},
{" ", "|_|", " |",},
{" _ ", "|_ ", " _|",},
{" _ ", "|_ ", "|_|",},
{" _ ", " |", " |",},
{" _ ", "|_|", "|_|",},
{" _ ", "|_|", " _|",},};
num x[6];
int tx[6];
void print(num t) {
for (auto i: t)
cout << i << "\n";
}
string str;
int hh, mm, ss;
int32_t main() {
for (int j = 0; j < 3; j++) {
getline(cin, str);
for (int i = 0, l = 0; i < 18; i += 3, l++)
x[l][j] = str.substr(i, 3);
}
for (int i = 0; i < 6; i++)
for (int j = 0; j < 10; j++)
if (x[i] == s[j]) tx[i] = j;
hh = tx[0] * 10 + tx[1], mm = tx[2] * 10 + tx[3], ss = tx[4] * 10 + tx[5];
int a = hh * 60 * 60 + mm * 60 + ss;
for (int j = 0; j < 3; j++) {
getline(cin, str);
for (int i = 0, l = 0; i < 18; i += 3, l++)
x[l][j] = str.substr(i, 3);
}
for (int i = 0; i < 6; i++)
for (int j = 0; j < 10; j++)
if (x[i] == s[j]) tx[i] = j;
hh = tx[0] * 10 + tx[1], mm = tx[2] * 10 + tx[3], ss = tx[4] * 10 + tx[5];
int b = hh * 60 * 60 + mm * 60 + ss;
int c = abs(a - b);
ss = c % 60, mm = c / 60, hh = mm / 60, mm %= 60;
tx[0] = hh / 10, tx[1] = hh % 10, tx[2] = mm / 10, tx[3] = mm % 10, tx[4] = ss / 10, tx[5] = ss % 10;
for( int i = 0 ; i < 6 ; i ++ )
x[i] = s[tx[i]];
if( a < b ) cout << "late\n";
else if( a > b ) cout << "early\n";
else cout << "gang gang hao\n";
for( int j = 0 ; j < 3 ; j ++ ){
for( int i = 0 ; i < 6 ; i ++ ) cout << x[i][j];
cout << "\n";
}
return 0;
}
H. 简单的 LRU 问题
模拟题,用一下语法糖快速的转换进制会简单一些,但是注意不能有行末空格,我因为这个WA2次
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
auto to_num = [](int x, int y) {
ostringstream ss;
string num;
ss << "0x" << setfill('0') << setw(y) << hex << x;
return ss.str();
};
int n = read(), m = read();
string line = "+------+";
char tab = '|';
for (int i = 1; i <= n; i++) line += "--------+";
line += "\n";
// title
cout << line;
cout << "| |";
for (int i = 0; i < n; i++)
cout << " "<< to_num(i, 2) << " |";
cout << "\n" << line;
vector<pair<int, int> > ram;
for (int i = 0, x, f; i < m; i++) {
cout << "| " << to_num(i, 2) << " |";
x = read(), f = 0;
for (auto &[k, v]: ram)
if (v == x) k = i, f = 1;
if (f == 0 && ram.size() < n) ram.emplace_back(i, x), f = 1;
if (f == 0) {
sort(ram.begin(), ram.end());
ram[0].first = i, ram[0].second = x;
f = 1;
}
sort(ram.begin(), ram.end());
for (auto [k, v]: ram) {
cout << " " << to_num(v, 4) << " |";
}
for (int i = ram.size() + 1; i <= n; i++)
cout << " |";
cout << "\n" << line;
}
return 0;
}
I. 好想听肆宝唱歌啊
排序,读入可以整行读入,也可以一个单词一个单词读入
#include<bits/stdc++.h>
using namespace std;
void solve(){
string s , ch = " ";
vector<pair<int,string>> a;
while( true ){
cin >> s;
if( s.back() == '.' || s.back() == '!' || s.back() == '?' ){
ch[1] = s.back();
a.emplace_back( 0 , s.substr( 0 , s.size()-1) );
break;
}else a.emplace_back( 0 , s );
}
int n = a.size();
for( int i = 0 , j = 1 ; j <= n ; j += 2 , i ++ ) a[i].first = j;
for( int i = n-1 , j = 2 ; j <= n ; j += 2 , i -- ) a[i].first = j;
sort(a.begin(), a.end());
for( auto [ k , v ] : a )
cout << v << ( ch[k==n] );
cout << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
int n; cin >> n;
vector< pair<int,string> > v(n);
for(auto &[ w , s ] : v) cin >> w >> s;
sort( v.begin() , v.end() , greater<pair<int,string>>() );
int k ; cin >> k;
cout << v[k].second;
return 0;
}
J. 毁灭凤凰人
胜利条件两种
- 有一张ATK大于毁灭凤凰人的0牌和一张1牌
- 有一张2牌和一张任意牌
注意大于等于2500或大于2100
#include<bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x;
}
int s[2] = {2500,2101};
int32_t main() {
int n = read() , m = read();
m = s[m];
int a = 0 , b = 0 , c = 0;
for( int x , i = 1 ; i <= n ; i ++ ){
x = read();
if( x == 0 ) a = max( a , read() );
else if( x == 1 ) b ++;
else c ++;
}
if( n > 1 && c > 0 ) printf("haoye\n");
else if( a >= m && b > 0 ) printf("haoye\n");
else printf("QAQ\n");
return 0;
}
K. 欢迎来到杭师大
注意换行
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
for( ; n ; n -- )
cout <<"Welcome to HZNU\n";
}
L. Ayanoto 变形记
除非x=0
,否则nx
一定可以到达
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n , x;
cin >> n >> x;
if( x ) cout << "yes\n";
else cout << "no\n";
}
int32_t main() {
ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
int t ; cin >> t;
while( t -- ) solve();
return 0;
}
M. P 龙学长的教诲
重新编一下号就行
#include<bits/stdc++.h>
using namespace std;
void solve(){
string s , ch = " ";
vector<pair<int,string>> a;
while( true ){
cin >> s;
if( s.back() == '.' || s.back() == '!' || s.back() == '?' ){
ch[1] = s.back();
a.emplace_back( 0 , s.substr( 0 , s.size()-1) );
break;
}else a.emplace_back( 0 , s );
}
int n = a.size();
for( int i = 0 , j = 1 ; j <= n ; j += 2 , i ++ ) a[i].first = j;
for( int i = n-1 , j = 2 ; j <= n ; j += 2 , i -- ) a[i].first = j;
sort(a.begin(), a.end());
for( auto [ k , v ] : a )
cout << v << ( ch[k==n] );
cout << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
int t ; cin >> t;
while( t -- ) solve();
return 0;
}
标签:ch,int,while,read,Hangzhou,4th,&&,Freshman,getchar
From: https://www.cnblogs.com/PHarr/p/17131773.html