3.11组队训练

本文介绍了如何使用C++中的STL容器map实现音阶映射,通过读入音符并调整其映射值来判断和弦类型。重点讲解了如何计算和弦构成(major triad, minor triad, dissonance)的算法。
摘要由CSDN通过智能技术生成

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值