A.Chord(stl容器map的使用阅读理解题)
建立起音和整数的映射即可。先搞一个初始映射:C 映射为 0,C# 映射为 1,...,B 映射为11。
然后依次读入三个音。𝑁1 的初始映射值就作为其真实映射值。如果 𝑁2 的初始映射值比 𝑁1 小,就加上 12,作为其真实映射值;如果 𝑁3 的初始映射值比 𝑁2 的真实映射值小,就不断地加上 12(其实至多加 2 次),直到超过 𝑁2 的真实映射值最后根据相邻两个音所对应的真实映射值的差进行判断即可。
#include<iostream> #include<cstdio> #include<string> #include<vector> #include<algorithm> #include<map> #include<cmath> using namespace std; typedef int ll; vector<string> v; const ll N = 1e5 + 7; ll a[N], b[N],cnt; map<string, ll> mp; void init() { mp["C"] = 1; mp["C#"] = 2; mp["D"] = 3; mp["D#"] = 4; mp["E"] = 5; mp["F"] = 6; mp["F#"] = 7; mp["G"] = 8; mp["G#"] = 9; mp["A"] = 10; mp["A#"] = 11; mp["B"] = 12; } int main() { ios::sync_with_stdio(false); cin.tie(0); ll t; cin >> t; init(); while (t--) { string s; ll n[4]; for (int i = 1; i <= 3; i++) { cin >> s; n[i] = mp[s]; if (i > 1 && n[i] < n[i - 1])n[i] += 12; } ll a, b; a = n[2] - n[1]; b = n[3] - n[2]; if (a == 4 && b == 3)cout << "Major triad" << endl; else if (a == 3 && b == 4)cout << "Minor triad" << endl; else cout << "Dissonance" << endl; } }
B.Problem Select(签到题)
把字符串末尾的数提取出来,sort后取前 𝑘 个输出即可
#include<iostream> #include<cstdio> #include<string> #include<vector> #include<algorithm> #include<map> #include<cmath> #include <iomanip> using namespace std; typedef long long ll; vector<string> v; map<ll, ll> num; ll a, b, n[1007]; int main() { ios::sync_with_stdio(false); cin.tie(0); ll t; cin >> t; while (t--) { string s; cin >> a >> b; for (int i = 1; i <= a; i++) { cin >> s; n[i] = 0; ll c = 1; for (int j = s.size() - 1; isalnum(s[j]); j--) { n[i] += (ll)(s[j] - '0') * c; c *= 10; } } sort(n + 1, n + 1 + a); for (int i = 1; i <= b; i++) { cout << n[i]; if (i < b)cout << " "; } cout << endl; } }
C.String Game(二维数组dp)
设状态 dp[𝑖] [𝑗] 为 B 的前 j 个字符在 A 的前 i 个字符中出现多少次。
状态转移方程 dp[𝑖] [𝑗] =dp[𝑖-1] [𝑗]+dp[𝑖] [𝑗-1]. (S1[i]==s2[j])
dp[𝑖] [𝑗] =dp[𝑖] [𝑗-1] (s1[i]!=s2[j])
#include <string> #include <iostream> using namespace std; const int N=5010; const int mod=1e9+7; int dp[N][N]; string s1,s2; int main() { while(cin>>s1>>s2){ for(int i=0;i<=s1.length();++i) dp[0][i]=1; for(int i=1;i<=s2.length();++i){ for(int j=1;j<=s1.length();++j){ dp[i][j]=0; } } for(int i=1;i<=s2.length();++i){ for(int j=1;j<=s1.length();++j){ if(s1[j-1]==s2[i-1]) dp[i][j]=(dp[i-1][j-1]+dp[i][j-1])%mod; else dp[i][j]=dp[i][j-1]%mod; } } cout<<dp[s2.length()][s1.length()]<<endl; } return 0; }
E.Shorten The Array(思维)
序列可分为下列三种情况:
情况 1: 最小值 min 只有一个。利用此最小值向左右任意% 其
他数,就可以把序列缩减为 1
情况 2:最小值 min 有 N 个,但是存在一个数 X 不是最小值
的倍数。可以利用 X 最近的一个 min,让该 min% 别的数靠
近 X,利用 X%min 一定小于 min,可以构造出一个单一最小
值,转化为情况 1,答案为 1。
情况 3:最小值 min 有 N 个,且其余数均为 min 的倍数。只
能让 min 把其余大数都删去,然后 min 之间两两抵消归零。
答案为 ⌈ 𝑁/2 ⌉。
#include <algorithm> #include <iostream> using namespace std; const int N=1e6+7; const int inf=0x3f3f3f3f; int T,n,cnt,s; int a[N]; int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>T; while(T--){ cin>>n; s=inf; cnt=0; for(int i=1;i<=n;++i){ cin>>a[i]; } for(int i=1;i<n;++i){ s=min(s,min(a[i],a[i+1])); if(a[i]%a[i+1]!=0) s=min(s,a[i]%a[i+1]); if(a[i+1]%a[i]!=0) s=min(s,a[i+1]%a[i]); } for(int i=1;i<=n;++i) { if(s==a[i]) cnt++; } if(cnt==0) cout<<1<<endl; else if(cnt%2==0) cout<<cnt/2<<endl; else cout<<cnt/2+1<<endl; } return 0; }
F.Queue(板子➕暴力)
先跑一遍逆序对:树状数组或者归并排序均可。
注意到每次交换只有 𝑙 到 𝑟 之间的数会对逆序对产生影响。
注意 𝑟 -𝑙 ≤ 100, 对 10^3 次询问,每次直接 𝑂(𝑟- 𝑙) 暴力统计逆序对变化情况即可。
#include <algorithm> #include <vector> #include <string> #include <map> #include <queue> #include <stack> #include <queue> #include <iostream> #define ll long long using namespace std; const int N=1e5+7; ll maxx,tree[N],a[N],T; ll x,y,n,q,k,cnt; ll lowbit(ll x){ return x&(-x); } void update(ll x){ for(ll i=x;i<=maxx;i+=lowbit(i)){ tree[i]++; } } ll ask(ll x){ ll ans=0; for(ll i=x;i;i-=lowbit(i)){ ans+=tree[i]; } return ans; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>T; while(T--){ maxx=0; cin>>n; for(ll i=1;i<=n;++i){ cin>>a[i]; a[i]++; maxx=max(a[i],maxx); } for(ll i=0;i<=maxx;++i){ tree[i]=0; } k=0; for(ll i=n;i>=1;--i){ k+=ask(a[i]-1); update(a[i]); } cin>>q; cnt=k;//到这里都是板子求逆序对 //开始暴力查询 while(q--){ cin>>x>>y; for(ll i=x;i<=y;++i){ if(a[y]<a[i]) --k; } for(ll i=x;i<y;++i){ if(a[x]>a[i]) --k; } swap(a[x],a[y]); for(ll i=x;i<=y;++i){ if(a[x]>a[i]) ++k; } for(ll i=x+1;i<y;++i){ if(a[y]<a[i]) ++k; } //输出最小值 cnt=min(cnt,k); } cout<<cnt<<endl; } return 0; }
G.Matrix(一道数学规律题)
大佬题解:设 𝑥 的约数个数为 𝑑 𝑥,则对于元素 𝑎 𝑖 𝑗,它会被翻转 𝑑 𝑖 × 𝑑 𝑗次。
这意味着,当且仅当 𝑖 和 𝑗 的约数个数均为奇数时,𝑎**𝑖 𝑗 最终才取 1。由数论知识易知,一个正整数的约数个数为奇数,当且仅当它是完全平方数。
因此,有 𝑛 行 𝑚 列矩阵的答案就是行列下标均为完全平方数的元素个数,即 ⌊√𝑛⌋ × ⌊√𝑚⌋。
训练时,直接通过打表和提交人数变多而猜出结论,直接冲一发就过了
#include <cmath> #include <iostream> using namespace std; #define ll long long ll n,m,t,s; int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>t; while(t--){ cin>>n>>m; s=(ll)(sqrt(n))*(ll)(sqrt(m)); cout<<s<<endl; } return 0; } L.Swimmer(水题,开long long)
#include<iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include<iomanip> using namespace std; const int N = 1e6 + 7; const double def = 1e-6; typedef long long ll; ll speed[N]; void program() { ll n, m, q; cin >> n >> m >> q; for (ll i = 1; i <= n; i++) { cin >> speed[i]; } for (ll i = 0; i < q; i++) { ll tim, player, pos; cin >> tim >> player; pos = (speed[player] * tim) % (2 * m); if (pos > m) { pos = 2 * m - pos; } cout << pos << '\n'; } } int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); program(); return 0; }