暑假考题总结
CSP-S 2023
一道很水的题目,我们可以直接用 \(9^5\) 通过。
Code
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#define prt printf
#define ll long long
#define int long long
#define spc putchar(' ')
#define ent putchar('\n')
#define pr_ prt("---")
#define prx prt("***")
#define prtn (putchar('N') , putchar('o'))
#define prty (putchar('Y') , putchar('e') , putchar('s'))
using namespace std;
inline int read(){
int f = 1 , k = 0 ;
char c = getchar() ;
while((c < '0') | (c > '9')) { f = (c == '-' ? -1 : 1) ; c = getchar() ;}
while((c >= '0') & (c <= '9')) { k = (k << 3) + (k << 1) + (c ^ 48) ; c = getchar() ;}
return f == - 1 ? -k : k ;
}
void output(int now){
if(now < 0){
putchar('-');
output(- now);
}
else{
if(now > 9) output(now / 10);
putchar((now % 10) ^ 48);
}
}
const int maxn = 1e5 + 1 , mod = 10;
int n , s1[10] , s2[10] , s3[10] , s4[10] , s5[10] , ans = 0;
bool vis[10][10][10][10][10] , a[10][10][10][10][10][10];
bool check(int i , int j , int k , int l , int r){
for(int num = 1 ; num<=n ; num++) if(a[num][i][j][k][l][r] == false) return false;
return true;
}
signed main(){
n = read() ;
for(int i=1 ; i<=n ; i++){
s1[i] = read() , s2[i] = read() , s3[i] = read() , s4[i] = read() , s5[i] = read() ;
vis[s1[i]][s2[i]][s3[i]][s4[i]][s5[i]] = true;
}
for(int i=1 ; i<=n ; i++){
for(int j=1 ; j<=9 ; j++){
if(vis[(s1[i] + j) % mod][s2[i]][s3[i]][s4[i]][s5[i]] == false) a[i][(s1[i] + j) % mod][s2[i]][s3[i]][s4[i]][s5[i]] = true;
if(vis[s1[i]][(s2[i] + j) % mod][s3[i]][s4[i]][s5[i]] == false) a[i][s1[i]][(s2[i] + j) % mod][s3[i]][s4[i]][s5[i]] = true;
if(vis[s1[i]][s2[i]][(s3[i] + j) % mod][s4[i]][s5[i]] == false) a[i][s1[i]][s2[i]][(s3[i] + j) % mod][s4[i]][s5[i]] = true;
if(vis[s1[i]][s2[i]][s3[i]][(s4[i] + j) % mod][s5[i]] == false) a[i][s1[i]][s2[i]][s3[i]][(s4[i] + j) % mod][s5[i]] = true;
if(vis[s1[i]][s2[i]][s3[i]][s4[i]][(s5[i] + j) % mod] == false) a[i][s1[i]][s2[i]][s3[i]][s4[i]][(s5[i] + j) % mod] = true;
}
for(int j=1 ; j<=9 ; j++){
if(vis[(s1[i] + j) % mod][(s2[i] + j) % mod][s3[i]][s4[i]][s5[i]] == false) a[i][(s1[i] + j) % mod][(s2[i] + j) % mod][s3[i]][s4[i]][s5[i]] = true;
if(vis[s1[i]][(s2[i] + j) % mod][(s3[i] + j) % mod][s4[i]][s5[i]] == false) a[i][s1[i]][(s2[i] + j) % mod][(s3[i] + j) % mod][s4[i]][s5[i]] = true;
if(vis[s1[i]][s2[i]][(s3[i] + j) % mod][(s4[i] + j) % mod][s5[i]] == false) a[i][s1[i]][s2[i]][(s3[i] + j) % mod][(s4[i] + j) % mod][s5[i]] = true;
if(vis[s1[i]][s2[i]][s3[i]][(s4[i] + j) % mod][(s5[i] + j) % mod] == false) a[i][s1[i]][s2[i]][s3[i]][(s4[i] + j) % mod][(s5[i] + j) % mod] = true;
}
}
for(int i=0 ; i<=9 ; i++){
for(int j=0 ; j<=9 ; j++){
for(int k=0 ; k<=9 ; k++){
for(int l=0 ; l<=9 ; l++){
for(int r=0 ; r<=9 ; r++) if(check(i , j , k , l , r) == true) ++ ans;
}
}
}
}
return output(ans) , ent , 0 ;
}
这个题目肯定是没有蓝的。
看完题目易得出我们只需要知道当前字母上一个相同字母的下标,去做 \(DP\),我们只需要维护当前字符串是否为回文串就行了。
Code
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#define prt printf
#define ll long long
#define int long long
#define spc putchar(' ')
#define ent putchar('\n')
#define pr_ prt("---")
#define prx prt("***")
#define prtn (putchar('N') , putchar('o'))
#define prty (putchar('Y') , putchar('e') , putchar('s'))
using namespace std;
inline int read(){
int f = 1 , k = 0 ;
char c = getchar() ;
while((c < '0') | (c > '9')) { f = (c == '-' ? -1 : 1) ; c = getchar() ;}
while((c >= '0') & (c <= '9')) { k = (k << 3) + (k << 1) + (c ^ 48) ; c = getchar() ;}
return f == - 1 ? -k : k ;
}
void output(int now){
if(now < 0){
putchar('-');
output(- now);
}
else{
if(now > 9) output(now / 10);
putchar((now % 10) ^ 48);
}
}
signed main() {
int n = read() , ans = 0; vector<char> s(n + 1) ; vector<int> d(n + 1) , l(n + 1);
for(int i=1 ; i<=n ; i++) {s[i] = getchar() ; while(('a' > s[i]) | (s[i] > 'z')) s[i] = getchar() ;}
for(int i=1 ; i<=n ; i++) {
for(int j=i-1 ; j>0 ; j=l[j] - 1) {
if(s[i] == s[j]) {l[i] = j ; break ;}
}
if(l[i]) d[i] = d[l[i] - 1] + 1 , ans += d[i] ;
}
return output(ans) , ent , 0 ;
}
/*
l[i] 存储上一个跟 s[i] 相同字母的下标
l[j] ~ l[i] - 1 构成回文串那么 s[l[i]] == s[l[j] - 1],构成的回文串数量为 l[j] - 1 与前面字母构成的回文串数量 + 1
*/
这个题目是一个大模拟,只需要按题意一直维护给出的操作就行了。
Code
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#define prt printf
#define ll long long
#define int long long
#define spc putchar(' ')
#define ent putchar('\n')
#define pr_ prt("---")
#define prx prt("***")
#define prtn (putchar('N') , putchar('o'))
#define prty (putchar('Y') , putchar('e') , putchar('s'))
#define k(u) St[u].k
#define s(u) St[u].s
#define a(u) St[u].a
#define o(u) St[u].o
#define son(u) St[u].son
#define str(u) St[u].String
using namespace std;
inline int read(){
int f = 1 , k = 0 ;
char c = getchar() ;
while((c < '0') | (c > '9')) { f = (c == '-' ? -1 : 1) ; c = getchar() ;}
while((c >= '0') & (c <= '9')) { k = (k << 3) + (k << 1) + (c ^ 48) ; c = getchar() ;}
return f == - 1 ? -k : k ;
}
inline string read_s() {
string s ; char c = getchar() ;
while(('a' > c) | (c > 'z')) c= getchar() ;
while((('a' <= c) & (c <= 'z')) | (c == '.')) {
s += c ;
c = getchar() ;
}
return s ;
}
inline char read_c() {
char c = getchar() ;
while(('a' > c) | (c > 'z')) c = getchar() ;
return c ;
}
void output(int now){
if(now < 0){
putchar('-');
output(- now);
}
else{
if(now > 9) output(now / 10);
putchar((now % 10) ^ 48);
}
}
void Out(string now) {
int num = now.length() - 1;
for(int i=0 ; i<=num ; i++) putchar(now[i]) ;
ent ;
return ;
}
struct Type {
int son[505] , o[505] ;
string String[505] ;
int k , s , a ; // k , s , a , o 题目给出 , son 儿子节点编号 String 名字
}St[505];
int s[505] , a[505] , b[505] , f[505] , Cnt = 0 ;
string name[505] ;
map<string , int> ys ; //内存占用 + 映射
int Mx(int x , int y) { return x > y ? x : y ;}
int MN(int x , int y) { return x < y ? x : y ;}
void Solve_1(int u) {
// cout << "u = " << u << '\n' ;
if(! k(u)) return ; o(u)[1] = 0;
for(int i=2 ; i<=k(u); i++) {
int last = o(u)[i - 1] + s(son(u)[i - 1]) , pos = last ;
// output(last) , spc , output(pos) , ent ;
for(int j=last ; j<=last+a(son(u)[i]) ; j++) {
if(!(j % a(son(u)[i]))) {
pos = j ;
break ;
}
}
o(u)[i] = pos ;
}
int last = o(u)[k(u)] + s(son(u)[k(u)]) , pos = last ;
for(int j=last ; j<=last+a(u) ; j++) {
if(!(j % a(u))) {
pos = j ;
break ;
}
}
s(u) = pos ;
}
void insert(string now , int u , int v) { // name u val
++ k(u) ;
a(u) = Mx(a(u) , a(v)) ;
son(u)[k(u)] = v ;
str(u)[k(u)] = now ;
}
void insert_(string now , int num) { // name u
name[++ Cnt] = now ;
f[Cnt] = num , s[Cnt] = s(num) , a[Cnt] = a(num) ;
int last = b[Cnt - 1] + s[Cnt - 1] , pos = last ;
for(int j=last ; j<=last+a[Cnt] ; j++) {
if(!(j % a[Cnt])) {
pos = j ;
break ;
}
}
b[Cnt] = pos ;
}
int find(int u , string now) {
string first , second ; int num = 0 , pos = 0 , len = (int)now.length() - 1;
while(now[num] != '.' && num <= len) { first += now[num] , ++ num ;} num ++;
while(num <= len) {second += now[num] , ++ num ;}
for(int i=1 ; i<=k(u) ; i++) {
if(str(u)[i] == first) { pos = i ; break ;}
}
int v = son(u)[pos] , val = o(u)[pos] ;
return second.empty() ? val : val + find(v , second) ;
}
string fs(int u , int x) {
if(! k(u)) return "" ;
int pos = 0 ;
for(int i=1 ; i<=k(u) ; i++) {
if((o(u)[i] <= x) & (x < o(u)[i] + s(son(u)[i]))) { pos = i ; break ;}
}
if(! pos) return "ERR" ;
string ans = fs(son(u)[pos] , x - o(u)[pos]) ;
return ans != "ERR" ? ans != "" ? str(u)[pos] + "." + ans : str(u)[pos] : "ERR";
}
void run_1() {
string of = read_s() ; int k = read() ;
ys[of] = ++ Cnt ;
for(int i=1 ; i<=k ; i++) {
string c = read_s() , now = read_s() ;
insert(now , Cnt , ys[c]) ;
}
Solve_1(Cnt) ;
output(s(Cnt)) , spc , output(a(Cnt)) , ent ;
}
void run_2() {
string c = read_s() , now = read_s() ;
insert_(now , ys[c]) ;
output(b[Cnt]) , ent ;
}
void run_3() {
string now = read_s() , first , second ; int num = 0 , pos = 0 , len = (int)now.length() - 1 ;
// cout << now << '\n' ;
while(now[num] != '.' && num <= len) { first += now[num] , ++ num ;} num ++;
while(num <= len) {second += now[num] , ++ num ;}
for(int i=1 ; i<=Cnt ; i++) {
if(name[i] == first) { pos = i ; break ;}
}
// cout << first << ' ' << second << ' ' << now << ' ' << pos << '\n' ;
output(second.empty() ? b[pos] : b[pos] + find(f[pos] , second)) , ent ;
}
void run_4() {
int k = read() , pos = 0 ;
for(int i=1 ; i<=Cnt ; i++) {
if(b[i] <= k && k < b[i] + s[i]) {
pos = i ;
break ;
}
}
if(! pos) { return puts("ERR") , (void)0 ;}
string now = name[pos] , ans = fs(f[pos] , k - b[pos]) ;
return Out(ans != "ERR" ? ans != "" ? name[pos] + "." + ans : name[pos] : "ERR") , (void)0 ;
}
void init() {
Cnt = 4 ;
for(int i=1 ; i<=4 ; i++) s(i) = a(i) = (1 << (i - 1)) ;
ys["byte"] = 1 ; ys["short"] = 2 ; ys["int"] = 3 ; ys["long"] = 4 ;
}
signed main() {
int T = read() ; init() ;
while(T --) {
int opt = read() ;
if(opt == 1) run_1() ;
if(opt == 2) run_2() ;
if(opt == 3) run_3() ;
if(opt == 4) run_4() ;
}
return 0 ;
}
这道题目赛时切出来那确实有亿点实力,这道题目正解是二分答案。
我们二分答案出最少需要的天数,然后取维护看是否符合所有条件。
标签:分析,10,now,putchar,OI,int,暑假,include,define From: https://www.cnblogs.com/CaoSheng-blog/p/18377443