A - Stair, Peak, or Neither?
水中之水题
void solve(){
CIN(a);CIN(b);CIN(c);
if(a<b&&b<c)cout<<"STAIR\n";
else if(b>a&&b>c)cout<<"PEAK\n";
else cout<<"NONE\n";
}
B - Upscaling
制表题,水题
string ANS[2]={"##",".."};
void solve(){
CIN(n);
FOR(i,1,2*n){
FOR(j,1,n){
cout<<ANS[(((i-1)/2+1)+j)%2];
}
cout<<ET;
}
}
C - Clock Conversion
格式转换,水题
void solve(){
SCIN(s);
int h=stoi(s.substr(0,2));
if(h<12){
if(h==0)cout<<"12"<<s.substr(2)<<" AM\n";
else cout<<s<<" AM\n";
}else{
if(h>12)h-=12;
if(h>=10)cout<<h<<s.substr(2)<<" PM\n";
else cout<<0<<h<<s.substr(2)<<" PM\n";
}
}
D - Product of Binary Decimals
大概思路
暴力打表判断即可
参考代码
bool ans[100005];
int lst[]={10,11,101,111,1001,1011,
1101,1111,10001,10011,10101,
11001,10111,11011,11101,11111};
void pre(){
sort(lst,lst+16);
}
void solve(){
CIN(n);
while(n>=10){
bool cg=1;
rFOR(i,15,0){
if(n%lst[i]==0){
n/=lst[i];
cg=0;
}
}
if(cg)break;
}
cout<<ANS[n==1];
}
E - Nearly Shortest Repeating Substring
大概思路
分解质因数,对第一段和第二段跑两遍模拟
参考代码
vector<int> d(int x) {//可以这样分解质因数,然后for(auto& i:dn)遍历,也可以直接FOR(i,1,n),然后if(n%i)continue;
vector<int> ans;
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
ans.push_back(i);
if (x / i != i)ans.push_back(x / i);
}
}
sort(ans.begin(), ans.end());
return ans;
}
void solve() {
CIN(n); SCIN(s);
FOR(i,1,n) {
if (n % i)continue;
int cnt = 0;
FOR(j, 0, n - 1) {
cnt += (s[j] != s[j % i]);
if (cnt > 1) break;
}
if (cnt <= 1) { cout << i << ET; return; }
cnt = 0;
FOR(j, 0, n - 1) {
cnt += (s[j] != s[j % i + i]);
if (cnt > 1) break;
}
if (cnt <= 1) { cout << i << ET; return; }
}
}
F - 0, 1, 2, Tree!
大概思路
实际上是算术题,先让子树数为2的节点按满二叉树尽可能排满,然后最后一排没排满的节点填上子树数为1的节点,判断最底层节点数是否等于题目提供的“子树数为0的节点个数”,再输出层数即可。
参考代码
int len(int x){return x>0?log2l(x)+1:0;}
void solve(){
CIN(a);CIN(b);CIN(c);
if(a==0){
if(c!=1){cout<<-1<<ET;return;}
cout<<b<<ET;return;
}
int al=len(a);//获得二叉树层数
int am=(a-(1ll<<(al-1))+1);//获得尽可能填满的二叉树最后一层有多少个“子树数为2”的节点数量
int br=((1ll<<(al-1))-am);//获得最后一层剩多少个空位
if(c!=br+am*2){cout<<-1<<ET;return;}//判断子树数为0的节点数量是否满足题意
if(b<=br){cout<<al<<ET;return;}//如果最后一层填不满,直接输出答案
b-=br;
cout<<al+b/(br+am*2)+(b%(br+am*2)!=0)<<ET;//如果能填满,就输出还要加多少层才能填满
}
G - Shuffling Songs
状压DP,可行性DP
大概思路
设dp[i][j]为“已选歌曲状态为i,最后一首为j,这种情况下是否可行” 然后写递推即可。
参考代码
bool dp[1<<16][16];
string a[16],b[16];
vector<int> e[16];
void dfs(int state,int now){
dp[state][now]=1;
for(auto &i:e[now]){
if((state&(1<<i))||dp[state|(1<<i)][i])continue;
dfs(state|(1<<i),i);
}
}
void solve(){
CIN(n);
FOR(i,1,(1<<n))FOR(j,0,n){
dp[i][j]=0;
}
FOR(i,0,n-1)e[i].clear();
FOR(i,0,n-1)cin>>a[i]>>b[i];
FOR(i,0,n-1)FOR(j,0,n-1){//建图优化字符串比较
if(a[i]==a[j]||b[i]==b[j]){
e[i].push_back(j);
e[j].push_back(i);
}
}
FOR(i,0,n-1){
dfs(1<<i,i);
}
int mx=0;
FOR(i,1,(1<<n))FOR(j,0,n){//收集答案
if(dp[i][j])mx=max(mx,__builtin_popcount(i));
}
cout<<n-mx<<ET;
}
附录
这里贴上用到的头部和main函数(有更新,for循环没事别开long long,常数大):
#include<iostream>
#include<vector>
#include<cmath>
#include<bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
#define ET '\n'
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define rFOR(i,a,b) for(int i=(a);i>=(b);i--)
//双向for循环
#define rep(i,a,b) for(int i=(a);i!=(b)+2*(a<b)-1;i+=2*(a<b)-1)
#define CIN(a) ll a;cin>>a
#define DCIN(a) ld a;cin>>a
#define SCIN(a) string a;cin>>a
#define CA cout<<ans<<ET
#define CY cout<<"YES"<<ET
#define CN cout<<"NO"<<ET
#define max(a,b) ((a>b)?(a):(b))
#define min(a,b) ((a<b)?(a):(b))
//没有C++20就不能用ranges了
//#define PP(l,r,CK) *ranges::partition_point(ranges::iota_view((l),(r)+1),(CK))
//string ANS[2]={"No\n","Yes\n"};
int M=1e9+7;
inline ll MO(ll x){return (x%M+M)%M;}
void solve(){
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//pre();
CIN(t);while(t--)
solve();
return 0;
}