首页 > 其他分享 >寒假训练第二周

寒假训练第二周

时间:2023-01-15 18:11:12浏览次数:45  
标签:std ch 训练 int ll long 第二周 寒假 define

寒假训练第二周

第一天

蓝桥杯模拟赛2

F.平面切分

大意:
N条直线,给定解析式,输出被分成的平面数

思路:
若所添加的直线与之前直线平行,平面数+1
若与已有直线每产生一个不同位置交点是,平面数额外+1
最后再加上原来的一个平面

代码:


#include <bits/stdc++.h>using namespace std;
#define ll long longconst ll N=1e5+10;
#define endl '\n'long double s[1010][2];
ll ans;
bool st[1010];
pair<long double,long double> p;
int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>s[i][0]>>s[i][1];
        set<pair<long double,long double>> points;
        for(int j=0;j<i;j++){
            if(st[j])continue;
            if(s[i][0]==s[j][0]){
                if(s[i][1]==s[j][1]){
                    st[i]= true;
                    break;
                }else continue;
            }
            p.first=(s[j][1]-s[i][1])/(s[i][0]-s[j][0]);
            p.second=s[i][0]*p.first+s[i][1];
            points.insert(p);
        }
        if(!st[i])ans+=points.size()+1;
    }
    cout<<ans+1;
    return 0;
}

第二天

牛客竞赛

1010 华华听月月唱歌

大意:
歌曲分成数个片段(有重复)
问最少几个片段可以还原整首歌曲

思路:
预先模拟

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=1e5+10;
#define endl '\n'
int main()
{
    int n,m,mi=0,ma=0,res=0;
    pair<int,int> pie[100007];
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>pie[i].first>>pie[i].second;
    }
    sort(pie,pie+m);
    for(int i=0;i<m;i++){
        if(pie[i].first>ma+1){
            cout<<-1;
            break;
        }
        if(pie[i].first>mi+1){
            res++;
            mi=ma;
        }
        if(pie[i].first<=mi+1){
            ma=max(ma,pie[i].second);
            if(ma>=n){
                cout<<res+1;
                break;
            }
        }
    }
    return 0;
}

第三天

中文个人赛

A.异或橙子

大意:
求区间中所有子区间的异或和的异或和
有修改和区间询问

思路:
一个数异或本身为0
找规律
当区间两端的数奇偶性不同时答案为0
相同时区间内奇偶性与端点一致时需进行异或
奇偶两个树状数组
lowbit(x) x&(-x)
修改操作:a[i]^x

代码:


#include <bits/stdc++.h>using namespace std;
#define ll long longconst ll N=2e5+10;
#define endl '\n'#define lowbit(x) x&(-x)int m,n;
int a[N];
struct name{
    int c[4*N];
    void add(int x,int y){
        for(int i=x;i<=n;i+=lowbit(i)){
            c[i]^=y;
        }
    }
    int sum(int x){
        int res=0;
        for(int i=x;i;i-= lowbit(i))res^=c[i];
        return res;
    }
}b[2];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(),cout.tie();
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i&1].add(i,a[i]);
    }
    while(m--){
        int op,i,j;
        cin>>op>>i>>j;
        if(op==1){
            b[i&1].add(i,a[i]^j);
            a[i]=j;
        }else{
            if((i&1)!=(j&1)) cout<<0<<endl;
            else{
                int op=b[i&1].sum(j)^b[i&1].sum(i-1);
                cout<<op<<endl;
            }
        }
    }
    return 0;
}

E.直播获奖

大意:
每计算出一名选手的分数,根据获奖比更新获奖选手数量以及分数线,输出每一次的分数线

思路:
动态维护获奖分数的最低分
对顶堆

代码:


#include <bits/stdc++.h>using namespace std;
#define endl '\n'#define ll long longconst ll N=1e5+10;
priority_queue<int> ma;
priority_queue<int, vector<int>, greater<int> > mi;
int n, w, now, num;
void qwq(){
    if (mi.size()<now)
    {
        mi.push(ma.top());
        ma.pop();
    }
    if (mi.size() > now)
    {
        ma.push(mi.top());
        mi.pop();
    }

}

void push(int num){
    if (num >= ma.top()) mi.push(num);
    else ma.push(num);
    qwq();
}

int main(){
    scanf("%d%d", &n, &w);
    ma.push(0);
    for (int p = 1; p <= n; p++)
    {
        now=max(1,p*w/100);
        scanf("%d", &num);
        push(num);
        printf("%d ", mi.top());
    }
    return 0;
}

第四天

cf#843 Div.2

A.A1. Gardener and the Capybaras (easy version)

大意:
把给定字符串分成三部分
让第二部分大于第一部分和第三部分或小与第一部分和第三部分

思路:
暴力

代码:

#include <bits/stdc++.h>using namespace std;void solve(){    string ch; cin >> ch;    int n = ch.size();    ch = ' ' + ch;    for(int i = 1; i < n; i ++)        for(int j = i + 1; j < n; j ++ )        {            string a = ch.substr(1, i), b = ch.substr(i + 1, j - i), c = ch.substr(j + 
1, n - j);            if((a <= b && c <= b) || (a >= b && c >= b))            {                cout << a << ' ' << b << ' ' << c << endl;                return;            }        }}int main(){    int T = 1;    cin >> T;    while( T -- ) solve();    return 0;}


第五天

cf排位赛

B.Hotpot

大意:
n个人,k种食材,m次操作
给定每人爱吃的食材,
轮到一个人,若此时没有他爱吃的则放入,否则吃掉,快乐+1
问每个人最后的快乐值

思路:
一轮下来,爱吃同一种食材的人分奇偶
故两轮一个循环
不足一轮的单独再跑

代码:

#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10;
struct f{
    int x;
    int happy;
}a[N];
int v[N];
long long n,k,m;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(v,0,sizeof(v));
        cin>>n>>k>>m;
        for(int i=0;i<n;i++){
            cin>>a[i].x;
            a[i].happy=0;
        }
        if(m>=2*n)
        {
            for(int i=0;i<2*n;i++)
            {
                int j=i%n;
                if(v[a[j].x]==0){
                    v[a[j].x]++;
                }else{
                    v[a[j].x]--;
                    a[j].happy++;
                }
            }
            for(int i=0;i<n;i++)
                a[i].happy*=(m/(2*n));
        }
        for(int i=0;i<m%(2*n);i++)
        {
            int j=i%n;
            if(v[a[j].x]==0)v[a[j].x]++;
            else
            {
                v[a[j].x]--;
                a[j].happy++;
            }
        }
        for(int i=0;i<n;i++)
        {
            if(i)cout<<" ";
            cout<<a[i].happy;
        }
        cout<<endl;
    }
    return 0;
}

第六天

每日一题

A.糖果

大意:
M种口味的糖果,K颗一包(注明口味),给定N包,问最少需几包能品尝到所有口味

思路:
二进制01状态表示一包中是否包含该口味
背包计算最少需几包

代码:


#include<bits/stdc++.h>using namespace std;
#define MAXN 105int N,M,K,tmp;
int f[1<<20],a[MAXN];
int main(){
    cin>>N>>M>>K;
    for(int i=0;i<N;i++){
        for(int j=0;j<K;j++){
            cin>>tmp;
            a[i]|=1<<tmp-1;
        }
    }
    memset(f,127,sizeof f);
    f[0]=0;
    for(int i=0;i<N;i++){
        for(int S=0;S<1<<M;S++){
            if(f[S]>MAXN)continue;
            f[S|a[i]]=min(f[S|a[i]],f[S]+1);
        }
    }
    cout<<(f[(1<<M)-1]<MAXN?f[(1<<M)-1]:-1)<<endl;
    return 0;
}

C.垒骰子

大意:
垒n个骰子,输入排斥对,排斥对不能紧挨,问有多少种垒的方式

思路:
dp
优化成矩阵乘法
矩阵快速幂

代码:


#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
ll n, m;
int a, b;
int opp[7] = {0, 4, 5, 6, 1, 2, 3};
struct Matrix {
    ll m[10][10];
    int row, col;
    Matrix (int r, int c, int fill) {
        row = r, col = c;
        for (int i = 1;i <= r;i ++)
            for (int j = 1;j <= c;j ++)
                m[i][j] = fill;
    }
    Matrix (int r) {
        row = r, col = r;
        memset (m, 0, sizeof m);
        for (int i = 1;i <= r;i ++)
            m[i][i] = 1;
    }

    ll Sum () {
        ll res = 0;
        for (int i = 1;i <= row;i ++)
            for (int j = 1;j <= col;j ++)
                res = (res + m[i][j]) % MOD;
        return res;
    }
};

Matrix Matrix_Mul (Matrix a, Matrix b) {
    Matrix c = Matrix(a.row, b.col, 0);
    for (int i = 1;i <= a.row;i ++)
        for (int j = 1;j <= b.col;j ++)
            for (int k = 1;k <= a.col;k ++)
                c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] % MOD) % MOD;
    return c;
}

Matrix KSM (Matrix matrix, ll p) {
    Matrix res = Matrix (6);
    while (p) {
        if (p & 1) res = Matrix_Mul (res, matrix);
        matrix = Matrix_Mul (matrix, matrix);
        p >>= 1;
    }
    return res;
}

int main(){
    cin >> n >> m;

    Matrix T = Matrix (6, 6, 4);
    Matrix A = Matrix (6, 1, 4);

    while (m -- ) {
        cin >> a >> b;
        T.m[opp[a]][b] = T.m[opp[b]][a] = 0;
    }
    Matrix T_pow = KSM (T, n-1);

    cout << Matrix_Mul (T_pow, A).Sum() << endl;

    return 0;
}

标签:std,ch,训练,int,ll,long,第二周,寒假,define
From: https://www.cnblogs.com/wwww-/p/17053870.html

相关文章