现场A题是不可能A多少题的,只能靠赛后补补题这样维持生活~
A:AOE还是单体?
思路:贪心,只有人数 > x 我们才会选择团体技能,<= x就直接单体技能就好了。
人数 > x的时候,先排个序,前面n - x个人全部团体技能,后面的全部单体技能。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 10;
typedef long long int ll;
ll a[maxn];
void solved(){
    int n,x;cin>>n>>x;
    ll s = 0;
    for(int i = 1; i <= n; i++)cin>>a[i],s+=a[i];
    if(n <= x){
        cout<<s<<endl;
    }else{
        sort(a + 1, a + 1 + n);
        ll ans = a[n - x] * x;
        for(int i = n - x + 1; i <= n; i++)ans += a[i] - a[n - x];
        cout<<ans<<endl;
    }
}
int main(){
    solved();
    return 0;
} 

C:白魔法师
思路:先用并查集把白色的联通块并起来并且计算这个联通块的个数,然后用邻接表存树(方便我们对黑色的点求联通块)。然后遍历顶点,对于黑色顶点遍历它的所有边,把相邻的白色联通块个数加起来找最大值。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
char s[maxn << 1];
int f[maxn << 1];//f[i]:i的父节点编号 
int siz[maxn << 1];//siz[i]:i的联通块大小 
vector<int>G[maxn];
int find(int x){
    if(f[x] != x){
        return f[x] = find(f[x]);
    }
    return f[x];
}
void unio(int u,int v){
    int fa = find(u),fb = find(v);
    if(fa != fb){
        if(siz[fa] > siz[fb]){
            f[fb] = fa;
            siz[fa] += siz[fb];
        } else{
            f[fa] = fb;
            siz[fb] += siz[fa];
        }
    }
}
void solved(){
    int n;cin>>n; 
    scanf("%s", s + 1);
    for(int i = 1; i <= n; i++)siz[i] = 1;
    for(int i = 1; i <= n; i++)f[i] = i;
    for(int i = 1; i <= n - 1; i++){
        int u,v;cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
        if(s[u] == s[v] && s[u] == 'W')unio(u,v);
    }
    for(int i = 1; i <= n; i++)
        if(s[i] == 'W')
            siz[i] = siz[find(i)];
    int ans = 0;
    for(int i = 1; i <= n; i++){
        if(s[i] == 'B'){
            int mm = 1;
            for(int j = 0; j < G[i].size(); j++){
                if(s[G[i][j]] == 'W'){
                    mm += siz[G[i][j]];
                }
            }
            ans = max(ans,mm);
        }
    }
    if(ans == 0)
    cout<<n<<endl;
    else cout<<ans<<endl;
}
int main(){
    solved();
    return 0;
} 

D:抽卡
思路:正着计算概率比较复杂,考虑用。 其中 .因为最终结果是 图片说明 图片说明
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;
const ll mod = 1e9 + 7;

const int maxn = 1e5 + 10;
ll a[maxn],b[maxn];
ll fastpow(ll a,ll b){
    ll ans = 1;
    while(b){
        if(b & 1){
            ans = ans * a % mod;
        }
        b >>= 1;
        a = a * a% mod;
    }
    return ans;
}
ll inv(ll a){
    return fastpow(a,mod - 2);
}
void solved(){
    int n;cin>>n;
    for(int i = 1; i <= n; i++)cin>>a[i];
    for(int i = 1; i <= n; i++)cin>>b[i];
    int ans = 1;
    for(int i = 1; i <= n ;i++) {
        ans = ans * (a[i] - b[i]) % mod * inv(a[i]) % mod;
    }
    cout<<(1 - ans + mod) % mod<<endl;
}
int main(){
    solved();
    return 0;
}

E:点击消除
思路:模拟,这个题其实就是括号匹配用栈去模拟就好了。
代码:

#include<bits/stdc++.h>
using namespace std;

void solved(){
    string s;cin>>s;
    stack<char>st;
    for(int i = 0; i < s.size(); i++){
        if(st.empty())st.push(s[i]);
        else if(st.top() == s[i]){
            st.pop();
        }else{
            st.push(s[i]);
        }
    }
    string ans;
    while(!st.empty()){
        ans += st.top();st.pop();
    }
    reverse(ans.begin(),ans.end());
    if(ans == "")
        cout<<"0"<<endl;
    else cout<<ans<<endl;
}
int main(){
    solved();
    return 0;
}

F:疯狂的自我检索者
思路:签到题~直接求和最高取5最低取1。。。。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 10;
typedef long long int ll;
int a[maxn];
void solved(){
    int n,m;cin>>n>>m;
    ll s = 0;
    for(int i = 1; i <= n - m; i++){
        cin>>a[i];s += a[i];
    }
    printf("%.5lf %.5lf\n",(s + m) * 1.0 / n,(s + m * 5) * 1.0 / n);
}
int main(){
    solved();
    return 0;
} 

G:解方程
思路:容易发现这个函数是一个单调递增的函数,所以用二分求。(参考兰子姐姐的写法
代码:

#include<bits/stdc++.h>
using namespace std;

int a;
long double b,c;
long double check(long double l,long double r){
    if(r - l <= 1e-8)return l;
    long double mid = (r + l) / 2;
    long double temp = 1;
    for(int i = 1; i <= a; i++) temp *= mid;
    if(temp + b * log(mid) < c)return check(mid,r);
    else return check(l,mid); 
}
void solved(){
    cin>>a>>b>>c;
    printf("%.7Lf\n",check(1,c));
}
int main(){
    solved();
    return 0;
}

H:神奇的字母(二)
思路:签到题,直接map统计一下每个字符出现最多次数就好了。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4;

int main(){
    string s;
    while(cin>>s);
    map<char,int>mp;
    for(int i = 0; i < s.size(); i++){
        mp[s[i]]++;
    }
    map<char,int>::iterator it = mp.begin();
    char ss;
    int ans = 0;
    for(;it!=mp.end();it++){
        if(it->second > ans){
            ans = it->second;
            ss = it->first;
        }
    }
    cout<<ss<<endl;
    return 0;
}

I:十字爆破
思路:这个题寒假集训出过一次,统计每行每列的增量,然后计算a(i,j)就是这一行的所有值+这一列的所有值-a(i,j)就好了,不过这题会卡空间,所以用一维数组存,怎么二维转一维呢(i - 1) * m + j就好了。
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;
const int maxn = 1e6 + 100;
ll a[maxn],b[maxn],c[maxn];
void solved(){
    ll n,m;scanf("%lld%lld",&n,&m);
    ll tot = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            ll x;scanf("%lld",&x);
            c[tot++] = x;
            a[i] += x;b[j] += x; 
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            ll v = c[(i - 1) * m + j];
            printf("%lld ",v + (a[i] - v) + (b[j] - v));
        }
        printf("\n");
    }
}
int main(){
    solved();
    return 0;
}