暑假集训CSP模拟一

赛时rank 14 T1 0,T2 0,T3 100,T4 0

T1大模拟出题人_______

T1 Start

大模拟,注意细节。

点此查看代码
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
    FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
#endif
using ll = long long;using ull = unsigned long long;
int n,m,k,now,nowp,sgn = 1;
struct node{
    string name;
    vector<string> nor,abnor;
    bool Double = false;
}a[40];
queue<string> Card;
inline bool is_normal(string s){return (s!="PASS"&&s!="DOUBLE"&&s!="TURN");}
inline void Print_Used(string name,string card){cout<<name+" used "+card+",now p="<<nowp<<".\n";}
inline void change_now(int &now,int delta){now += delta;if(now <= 0) now += n;if(now > n) now -= n;}
inline void get_new_card(int now){
    string s = Card.front();Card.pop();
    if(is_normal(s)) a[now].nor.push_back(s);
    else a[now].abnor.push_back(s);
}
inline bool del_double_by_solve(string aim){
    for(auto i = a[now].abnor.begin();i != a[now].abnor.end(); ++i)
        if((*i) == "") a[now].abnor.erase(i);
    for(auto i = a[now].abnor.begin();i != a[now].abnor.end();++i){
        if((*i) == aim){
            Print_Used(a[now].name,*i);
            a[now].abnor.erase(i);
            get_new_card(now);
            a[now].Double = false;
            return true;
        }
    }
    return false;
}
inline int get_order(char s){
    if(s == 'C') return 4;
    else if(s == 'A') return 3;
    else if(s == 'B') return 2;
    else if(s == 'D') return 1;
    else return 0;
}
inline int get_nxtp(int p,string s){
    int x = 0;
    for(int i = 1;i < s.size(); ++i) x = x*10+(s[i]-'0');
    if(s[0] == 'A') return p+x;
    else if(s[0] == 'B') return p-x;
    else if(s[0] == 'C') return p*x;
    else if(s[0] == 'D') return (int)(floor(1.0*p/x));
    else return x;
}
inline void Print_Lost(string name){cout<<name+" lost the game.\n";}
inline int Get_Order(char s){
    if(s == 'D') return 4;
    if(s == 'B') return 3;
    if(s == 'A') return 2;
    if(s == 'C') return 1;
    return 0;
}
inline void Work(){
    while(true){
        // for(auto i:a[now].nor) cout<<i<<' ';
        // cout<<' ';
        // for(auto i:a[now].abnor) cout<<i<<' ';
        if(a[now].Double){
            if(del_double_by_solve("PASS")) change_now(now,sgn),a[now].Double = true;
            else if(del_double_by_solve("TURN")) sgn = -sgn,change_now(now,sgn),a[now].Double = true;
            else if(del_double_by_solve("DOUBLE")) change_now(now,sgn),a[now].Double = true;
            else{
                pair<int,pair<string,vector<string>::iterator> > max1;
                max1.first = INT_MAX;
                for(auto i = a[now].nor.begin();i != a[now].nor.end();++i){
                    if((*i) == ""){continue;}
                    int emm = get_nxtp(nowp,*i);
                    if(emm < max1.first || (emm == max1.first && Get_Order(max1.second.first[0])<Get_Order((*i)[0])))
                        max1 = make_pair(emm,make_pair(*i,i));
                }
                if(max1.first > 99){
                    vector<string>().swap(a[now].abnor);
                    vector<string>().swap(a[now].nor);
                    for(int i = 1;i <= 3; ++i) get_new_card(now);
                    return Print_Lost(a[now].name),void();
                }
                else{ 
                    nowp = max1.first,
                    Print_Used(a[now].name,max1.second.first),
                    get_new_card(now),
                    a[now].nor.erase(max1.second.second);
                }
                a[now].Double = false;
                goto K;
            }
            continue;
        }
        else{
            K:;
            pair<int,pair<string,vector<string>::iterator> > max1;
            max1.first = INT_MIN;
            for(auto i = a[now].nor.begin();i != a[now].nor.end(); ++i){
                if((*i) == "") {continue;}
                int emm = get_nxtp(nowp,*i);
                if(emm > 99) continue;
                if(emm > max1.first || (emm == max1.first && get_order((*i)[0]) > get_order(max1.second.first[0])))
                    max1 = make_pair(emm,make_pair(*i,i));
            }
            if(max1.first != INT_MIN){
                nowp = max1.first;
                Print_Used(a[now].name,max1.second.first);
                a[now].nor.erase(max1.second.second);
                get_new_card(now);
                change_now(now,sgn*1);
            }
            else{
                if(del_double_by_solve("PASS")) change_now(now,sgn);
                else if(del_double_by_solve("TURN")) sgn = -sgn,change_now(now,sgn);
                else if(del_double_by_solve("DOUBLE")) change_now(now,sgn),a[now].Double = true;
                else{
                    vector<string>().swap(a[now].abnor);
                    vector<string>().swap(a[now].nor);
                    for(int i = 1;i <= 3; ++i) get_new_card(now);
                    return Print_Lost(a[now].name),void();
                }
            }
        }
    }
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i = 1;i <= n; ++i){
        cin>>a[i].name;
        for(int j = 1;j <= 3; ++j){
            string s;cin>>s;
            if(is_normal(s)) a[i].nor.push_back(s);
            else a[i].abnor.push_back(s);
        }
    }
    for(int i = 1;i <= k; ++i){
        string s;cin>>s;Card.push(s);
    }
    now = 1;
    for(int i = 1;i <= m; ++i){
        cout<<"Round "<<i<<":\n";
        Work();
        for(int j = 1;j <= n; ++j) a[j].Double = false;
        nowp = 0;
        sgn = 1;
    }
}

T2 mine

递推,考虑当前位的贡献只与当前位,上一位,下一位有关

\(f_{i,0/1/2}\)表示第\(i\)位的下一位没有/有雷,第\(i\)位是雷时的方案数

当前位是\(0\)时,\(f_{i,0}=f_{i-1,0}\)

当前位是\(1\)时,\(f_{i,0} = f_{i-1,2},f_{i,1}=f_{i-1,0}\)

当前位是\(2\)时,\(f_{i,0}=f_{i-1,2}\)

当前位是\(*\)时,\(f_{i,2}=f_{i-1,1}+f_{i-1,2}\)

当前位是\(?\)时,\(f_{i,2}=f_{i-1,1}+f_{i-1,2},f_{i,0}=f_{i,1}=f_{i-1,0}+f_{i-1,2}\)

答案为\(f_{n,0}+f_{n,2}\)

点此查看代码
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
    FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
#endif
using ll = long long;using ull = unsigned long long;
const int N = 1e6 + 10 ,mod = 1e9 + 7;
char s[N];
int n,f[N][3];
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    cin>>(s+1);
    n = strlen(s+1);
    f[0][0] = f[0][1] = 1;
    for(int i = 1;i <= n; ++i){
        if(s[i] == '0') f[i][0] = f[i-1][0];
        if(s[i] == '1') f[i][0] = f[i-1][2],f[i][1] = f[i-1][0];
        if(s[i] == '2') f[i][1] = f[i-1][2];
        if(s[i] == '*') f[i][2] = (f[i-1][1]+f[i-1][2])%mod;
        if(s[i] == '?') f[i][2] = f[i-1][1] + f[i-1][2],f[i][0] = f[i][1] = (f[i-1][0]+f[i-1][2])%mod;
        f[i][0]%=mod;f[i][1]%=mod;f[i][2]%=mod;
    }
    cout<<(0ll+f[n][0]+f[n][2])%mod<<'\n';
}

T3 小凯的疑惑

\(gcd(x,y)\ne -1\)时,直接输出-1

证明显然,假设当前有一个数\(c\),那么若有\(ax+by=c\),则一定有\(gcd(x,y)\mid c\),若\(gcd(x,y)\ne 1\),则一定可以找出无穷个数,使得\(gcd(x,y)\nmid c\)

由于数据非常小,我们可以直接\(O(n)\)水过……

点此查看代码
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
    FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
#endif
long long LCM(int a,int b){
    return 1ll * a / __gcd(a,b) * b;
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    int x,y;
    cin>>x>>y;
    if(x > y) swap(x,y);
    if(x == 1) return puts("0"),0;
    if(__gcd(x,y) != 1) return puts("-1"),0;
    long long lcm = LCM(x,y),a = 0;
    for(int i = 0;;++i){
        long long emm = 1ll * i * y;
        if(emm + x > lcm) break;
        a += (lcm-emm-x+1)/x+1;
    }
    cout<<lcm-x+2-a<<'\n';
}

but,正解还是有必要想的

考虑这个暴力的实质,是将给数轴上标出的东西减去。

image

暴力是枚举\(x+0y,x+1y,x+2y,\ldots\)

列出式子,化一下就有了\(\sum_{i=0}^{x-1}\left\lfloor\frac{iy}{x}\right\rfloor\)

化简,两边同时乘上x,再将向下取整化成mod的形式

得到\(x\sum_{i=0}^{x-1}\left\lfloor\frac{iy}{x}\right\rfloor=\sum_{i=0}^{x-1}iy-\sum_{i=0}^{x-1}(iy\mod x)\)

等差数列求和,就有\(\frac{\frac{x(x-1)y}{2}-\frac{x(x-1)}{2}}{x}\)

\(\frac{(x-1)(y-1)}{2}\)

T4 春节十二响

简单的贪心,看代码

点此查看代码
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
    FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
#endif
using ll = long long;using ull = unsigned long long;
const int N = 2e5 + 10;
struct EDGE{int to,next;}edge[N<<1];
int head[N],cnt,d[N],son[N];
inline void add(int u,int v){edge[++cnt] = {v,head[u]};head[u] = cnt;}
bitset<N> vis;
int n,a[N];
priority_queue<int> q[N];
ll ans = 0;
inline void Merge(int x,int y){
    priority_queue<int> p;
    while(q[y].size()){
        p.push(max(q[x].top(),q[y].top()));
        q[x].pop();q[y].pop();
    }
    while(p.size()) q[x].push(p.top()),p.pop();
}
void dfs1(int x){
    d[x] = 1;
    for(int i = head[x]; i;i = edge[i].next){
        int y = edge[i].to;
        dfs1(y);
        if(d[y] > d[son[x]]) son[x] = y;
        d[x] = max(d[x],d[y]+1);
    }
}
void dfs(int x){
    if(son[x]){
        dfs(son[x]);
        q[x].swap(q[son[x]]);
    }
    for(int i = head[x]; i;i = edge[i].next){
        int y = edge[i].to;
        if(y == son[x]) continue;
        dfs(y);
        Merge(x,y);
    }
    q[x].push(a[x]);
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    cin>>n;
    for(int i = 1;i <= n; ++i) cin>>a[i];
    for(int i = 2,f;i <= n; ++i){
        cin>>f;
        add(f,i);
    }
    dfs1(1);
    dfs(1);
    while(q[1].size()) ans += q[1].top(),q[1].pop();
    cout<<ans<<'\n';
}
posted @ 2024-07-19 07:46  CuFeO4  阅读(7)  评论(0编辑  收藏  举报