码迷,mamicode.com
首页 > 其他好文 > 详细

The 10th Shandong Provincial Collegiate Programming Contest(8/13)

时间:2020-02-07 20:33:55      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:math   printf   end   签到   void   deb   break   its   sda   

\[The\ 10th\ Shandong\ Provincial\ Collegiate\ Programming\ Contest\]

\(A.Calandar\)

签到

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
char day[5][20] = {{"Monday"},{"Tuesday"},{"Wednesday"},{"Thursday"},{"Friday"}};
using LL = int_fast64_t;
int T;
void solve(){
    LL now = 0, y, m, d, nxt = 0;
    int cd;
    char s[20];
    scanf("%I64d %I64d %I64d %s",&y,&m,&d,s);
    if(s[0]=='M') cd = 0;
    else if(s[0]=='T' && s[1]=='u') cd = 1;
    else if(s[0]=='W') cd = 2;
    else if(s[0]=='T' && s[1]=='h') cd = 3;
    else cd = 4;
    now = 360 * y + 30 * m + d;
    scanf("%I64d %I64d %I64d",&y,&m,&d);
    nxt = 360 * y + 30 * m + d;
    LL delta = nxt - now;
    cd = ((cd+delta)%5+5)%5;
    printf("%s\n",day[cd]);
}
int main(){
    for(scanf("%d",&T); T; T--) solve();
    return 0;
}

\(B.Flipping\ Game\)

DP
\(f[i][j]\)表示当前第\(i\)轮按开关,和最终状态相反的有\(j\)个的方案数,初始有\(num\)个灯和最终状态不同的话,显然\(f[0][num]=1\)
现在考虑状态转移,\(kk\)表示上一轮与最终状态相反的个数,\(x\)表示有\(x\)个从和最终状态相反的变成和最终状态相同的,\(y\)表示从和最终状态相同的变成和最终状态不同的,则\(f[i][j]=\sum_{valid\ kk}f[i-1][kk]·C(kk,x)·C(n-kk,y)\)
其中需要满足四个约束条件:
1.\(0 \le x \le kk\)
2.\(0 \le y \le n-kk\)
3.\(x + y = m\)
4.\(kk-x+y=j\)
\(3\)\(4\)联立得到\(x=(kk+m-j)/2\)
然后就可以写了

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 111;
using LL = int_fast64_t;
const LL MOD = 998244353;
int T,n,m,k;
char s1[MAXN],s2[MAXN];
LL fact[MAXN],invfact[MAXN],f[2][MAXN];
LL qpow(LL a, LL b){
    LL res = 1;
    while(b){
        if(b&1) res = res * a % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return res;
}
LL C(int A, int B){ return fact[A] * invfact[B] % MOD * invfact[A-B] % MOD; }
void solve(){
    scanf("%d %d %d %s %s",&n,&k,&m,s1,s2);
    int num = 0;
    for(int i = 0; i < n; i++) num += (s1[i]!=s2[i]?1:0);
    memset(f,0,sizeof(f));
    int tag = 0;
    f[tag][num] = 1;
    for(int i = 1; i <= k; i++){
        tag ^= 1;
        memset(f[tag],0,sizeof(f[tag]));
        for(int j = 0; j <= n; j++){
            for(int kk = max(0,j-m); kk <= min(n,j+m); kk++){
                if((kk+m-j)&1) continue;
                int x = ((kk+m-j)>>1);
                if(x<0||x>kk||m-x<0||m-x>n-kk) continue;
                f[tag][j] = (f[tag][j] + f[tag^1][kk] * C(kk,x) % MOD * C(n-kk,m-x)) % MOD;
            }
        }
    }
    printf("%lld\n",f[tag][0]);
}
int main(){
    fact[0] = 1;
    for(int i = 1; i < MAXN; i++) fact[i] = fact[i-1] * i % MOD;
    for(int i = 0; i < MAXN; i++) invfact[i] = qpow(fact[i],MOD-2);
    for(scanf("%d",&T); T; T--) solve();
    return 0;
}

\(C.Wandering\ Robot\)

随便写

#include<bits/stdc++.h>
#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
using namespace std;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 1e5+10;
char a[N];
int32_t main(){
    IOS;
    int _;cin>>_;
    while(_--){
        int n,k; cin>>n>>k;
        cin>>a;
        int ans=0,x=0,y=0;
        for(int i=0;i<n;i++){
            if(a[i]=='R')x++;
            if(a[i]=='L')x--;
            if(a[i]=='U')y++;
            if(a[i]=='D')y--;
            ans=max(ans, abs(x)+abs(y));
        }
        if(k==1){
            cout<<ans<<endl;
            continue;
        }
        int xx=x*(k-1), yy=y*(k-1);
        for(int i=0;i<n;i++){
            if(a[i]=='R')xx++;
            if(a[i]=='L')xx--;
            if(a[i]=='U')yy++;
            if(a[i]=='D')yy--;
            ans=max(ans, abs(xx)+abs(yy));
        }
        cout<<ans<<endl;
    }
    return 0;
}

\(D.Game\ on\ a\ Graph\)

最终状态是一棵树,只和边的数量有关,最多可以删掉\(e-(v-1)\)条边

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
int T,n,v,e;
char s[MAXN];
void solve(){
    scanf("%d %s %d %d",&n,s,&v,&e);
    for(int i = 1; i <= e; i++) scanf("%d %d",&n,&n);
    n = strlen(s);
    putchar(s[(e-(v-1))%n]=='1'?'2':'1'); puts("");
}
int main(){
    for(scanf("%d",&T); T; T--) solve();
    return 0;
}

\(E.BaoBao\ Loves\ Reading\)

\(F.Stones\ in\ the\ Bucket\)

贪心,先变成\(n\)的倍数然后把低于平均数的补齐即可

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
using LL = int_fast64_t;
const int MAXN = 1e5+7;
int T,n;
LL A[MAXN];
void solve(){
    LL res = 0;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> A[i];
    LL tot = accumulate(A+1,A+1+n,0LL);
    LL del = tot % n, ave = tot / n;
    res = del;
    for(int i = 1; i <= n; i++){
        if(A[i]>ave&&del){
            LL d = min(del,A[i]-ave);
            del -= d;
            A[i] -= d;
        }
        if(!del) break;
    }
    for(int i = 1; i <= n; i++) if(A[i]<ave) res += ave - A[i];
    cout << res << endl;
}
int main(){
    ____();
    for(cin >> T; T; T--) solve();
    return 0;
}

\(G.Heap\)

\(H.Tokens\ on\ the\ Segments\)

优先考虑左端点靠前的,每当遍历到某\(x\)值时,把左端点为\(x\)的线段的右端点加入到优先队列中,把已经超过右边界的线段删去,然后取右端点最靠左的放token

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
int T,n;
pair<int,int> seg[MAXN];
void solve(){
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> seg[i].first >> seg[i].second;
    sort(seg+1,seg+1+n);
    int tot = 0, now = 1;
    priority_queue<int,vector<int>,greater<int>> que;
    for(int cur = 1; now<=n||!que.empty(); ){
        while(now<=n&&seg[now].first==cur){
            que.push(seg[now].second);
            now++;
        }
        while(!que.empty()&&que.top()<cur) que.pop();
        if(!que.empty()){
            tot++;
            que.pop();
        }
        if(!que.empty()) cur++;
        else{
            if(now>n) break;
            else cur = seg[now].first;
        }
    }
    cout << tot << endl;
}
int main(){
    ____();
    for(cin >> T; T; T--) solve();
    return 0;
}

\(I.Connected \Intervals\)

\(J.Triangle\ City\)

\(K.Happy\ Equation\)

\(L.Median\)

建大的向小的连边,同时建反图,如果图中存在环就直接全部输出0.
找每个点在拓扑排序序列中能够达到的最左端和最右端,如果\((n+1)/2\)在区间内的话,说明可以作为中位数,用bitset维护最少必经集合

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 111;
int T,n,m,deg[MAXN],rdeg[MAXN];
vector<int> G[MAXN],rG[MAXN];
bitset<MAXN> bst[MAXN],rbst[MAXN];
int toposort(){
    int tot = 0;
    queue<int> que;
    for(int i = 1; i <= n; i++) if(!deg[i]) que.push(i);
    while(!que.empty()){
        int u = que.front();
        que.pop();
        tot++;
        for(int v : G[u]){
            if(--deg[v]==0) que.push(v);
            bst[v] |= bst[u];
        }
    }
    return tot;
}
void rtoposort(){
    queue<int> que;
    for(int i = 1; i <= n; i++) if(!rdeg[i]) que.push(i);
    while(!que.empty()){
        int u = que.front();
        que.pop();
        for(int v : rG[u]){
            if(--rdeg[v]==0) que.push(v);
            rbst[v] |= rbst[u];
        }
    }
}
void init(){
    for(int i = 1; i <= n; i++){
        G[i].clear();
        rG[i].clear();
        rdeg[i] = 0;
        deg[i] = 0;
        bst[i].reset();
        bst[i].set(i);
        rbst[i].reset();
        rbst[i].set(i);
    }
}
void solve(){
    scanf("%d %d",&n,&m);
    init();
    for(int i = 1; i <= m; i++){
        int u, v;
        scanf("%d %d",&u,&v);
        G[u].emplace_back(v);
        rG[v].emplace_back(u);
        deg[v]++;
        rdeg[u]++;
    }
    int tot = toposort();
    if(tot!=n){
        for(int i = 0; i < n; i++) putchar('0');
        puts("");
        return;
    }
    rtoposort();
    for(int i = 1; i <= n; i++){
        int l = bst[i].count();
        int r = n-rbst[i].count()+1;
        if(l<=(n+1)/2 && (n+1)/2<=r) putchar('1');
        else putchar('0');
    }
    puts("");
}
int main(){
    for(scanf("%d",&T); T; T--) solve();
    return 0;
}

\(M. Sekiro\)

签到

include<bits/stdc++.h>

using namespace std;

define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

const int N = 1e5+10;
int main(){
IOS;
int t; cin>>t;
while(t--){
int n,k; cin>>n>>k;
if(!n){
cout<<0<<endl;
continue;
}
while(k--){
if(n&1)n++;
n>>=1;
if(n==1)break;
}
cout<<n<<endl;
}
return 0;
}

The 10th Shandong Provincial Collegiate Programming Contest(8/13)

标签:math   printf   end   签到   void   deb   break   its   sda   

原文地址:https://www.cnblogs.com/kikokiko/p/12274345.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!