2020 CCPC-Wannafly Winter Camp Day6

PTA
牛客

C. 酒馆战棋

贪心即可。


Code

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e3+5,MAXM = 1e6+5,MOD = 1e9+7,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;

int T,n,A,B,C,D;
char s[MAXN];
int solve1(int a,int b,int c,int d){
    int ans=0;
    for(int i=0;i<n;i++){
        if(s[i]=='0'){
            if(c + d){
                if(d)d--,c++;
            }else if(a+b){
                if(b)b--,a++;
            }
        }else{
            if(c+d){
                if(c)c--,ans++;
                else c++,d--;
            }else if(a+b){
                if(a)a--,ans++;
                else b--,a++;
            }
        }
    }
    return ans;
}

int solve2(int a,int b,int c,int d){
    int ans=0;
   for(int i=0;i<n;i++){
        if(s[i]=='0'){
            if(c + d){
                if(!c)d--,c++;
            }else if(a+b){
                if(!a)b--,a++;
            }
        }else{
            if(c+d){
                if(!d)c--,ans++;
                else c++,d--;
            }else if(a+b){
                if(!b)a--,ans++;
                else b--,a++;
            }
        }
    }
    return ans;
}

int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>T;
    while(T--){
        cin>>n>>A>>B>>C>>D;
        cin>>s;
        cout<<solve1(A,B,C,D)<<' '<<solve2(A,B,C,D)<<'\n';
    }
    return 0;
}

F. 图与三角形

容斥一下。
通过枚举角算出不合法的三角形个数,然后用总答案减去即可。
最后要除以一个\(2\),因为一个三角形不合法,就会存在两个角的两边不同色。


Code

#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define REPE(i,a,b) for(int i=(a); i<=(b); i++)
#define MAXN 5007
typedef long long ll;
typedef unsigned long long ull;
int rc[MAXN], bc[MAXN];
ull ans;
int main() {
    memset(rc,0,sizeof rc);
    memset(bc,0,sizeof bc);
    int n; scanf("%d", &n);
    int A,B,C,P,D; scanf("%d%d%d%d%d", &A, &B, &C, &P, &D);
    REPE(i,1,n) REPE(j,i+1,n) {
        if(((ll)A*(i+j)*(i+j)+(ll)B*(i-j)*(i-j)+C)%P>D) {
            bc[i]++, bc[j]++;
        } else {
            rc[i]++, rc[j]++;
        }
    }
    ans=0;
    REPE(i,1,n) {
        ans+=bc[i]*rc[i];
    }
    ans/=2;
    ans = (ull)n*(n-1)*(n-2)/6-ans;
    printf("%llu\n", ans);
}

J. K重排列

题意:
对于一个排列\(p[1\cdots n]\),设\(p^k[i]=p[p^{k-1}[i]]\),且\(p^1[i]=p[i]\)
如果存在一个\(k\),使得对于所有的\(i\)都有\(p^k[i]=i\),那么\(k\)\(p\)的一个周期。
最后统计满足\(k\)为其一个周期的排列个数。

思路:
题解已经说的很清楚了,在比赛的时候考虑的是将\(n\)个点划分为若干个循环,每个循环的长度整除\(k\)
然后想的是直接搜索,感觉问题应该不大...
直接附上题解说的吧。

给出暴力的代码:


Code

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 50+5,MAXM = 1e6+5,MOD = 998244353,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;
int n,T;
ll ans=0,K,fact[MAXN],inv[MAXN];

ll qpow(ll a,ll b){
    ll ans=1;
    for(;b;b>>=1,a=a*a%MOD)if(b&1)ans=ans*a%MOD;
    return ans;
}
ll C(int a,int b){
    if(a<b)return 0;
    if(a==b || b==0)return 1;
    return fact[a] * inv[a-b]%MOD*inv[b]%MOD;
}
void dfs(int sum,int pre,ll res,int cnt){
    if(!sum){
        res = res * inv[cnt]%MOD;
        ans = (ans + res)%MOD;
        //cout<<cnt<<' '<<res<<'\n';
        return ;
    }
    for(int i=pre;i<=sum;i++){
        if(K%i==0){
            //cout<<sum<<' '<<i<<' '<<C(sum,i)<<'\n';
            ll tmp = res * C(sum,i)%MOD*fact[i-1]%MOD;
            if(i != pre){
                tmp = tmp * inv[cnt] % MOD;
                dfs(sum-i,i,tmp,1);
            }else dfs(sum-i,i,tmp,cnt+1);
        }
    }
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    fact[1] = fact[0] = 1;
    for(int i=2;i<=50;i++)fact[i] = fact[i-1]*i%MOD;
    inv[50] = qpow(fact[50],MOD-2);
    for(int i=49;i>0;i--)inv[i] = inv[i+1]*(i+1)%MOD;
    inv[0]=1;
    cin>>T;
    while(T--){
        cin>>n>>K;
        ans = 0;
        dfs(n,1,1,0);
        cout<<ans<<'\n';
    }
    return 0;
}

K. 最大权值排列

接下来签到四连。


Code

扫描二维码关注公众号,回复: 9224336 查看本文章
/*
 * Author:  heyuhhh
 * Created Time:  2020/1/17 13:32:46
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

int n;

void run(){ 
    int now = 1;
    for(int i = 1; i <= n; i++) {
        cout << now << ' ';
        if(i <= (n - 1) / 2) now += 2;   
        else {
            if(now & 1) {
                if(n & 1) --now;
                else ++now;
            }
            else now -= 2;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}

L. 你吓到我的马了.jpg

BFS。


Code

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e2+5,MAXM = 1e6+5,MOD = 1e9+7,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;

int n,m;
int dx[8] = {-2,-2,2,2,-1,1,-1,1};
int dy[8] = {-1,1,-1,1,-2,-2,2,2};
int dx2[8] = {-1,-1,1,1,0,0,0,0};
int dy2[8] = {0,0,0,0,-1,-1,1,1};
char mp[MAXN][MAXN];
int vis[MAXN][MAXN];
inline bool bound(int x,int y){
    return x>=1&&x<=n&&y>=1&&y<=m;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>(mp[i]+1);
    }
    int sx,sy;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(mp[i][j]=='M'){
                sx = i,sy=j;
            }
        }
    }
    queue<pii> q;
    q.push({sx,sy});
    vis[sx][sy] = 1;
    pii nw;
    //cout<<sx<<' '<<sy<<'\n';
    while(!q.empty()){
        pii a = q.front();q.pop();
        for(int i=0;i<8;i++){
            nw.x = a.x + dx[i];
            nw.y = a.y + dy[i];
            if(bound(nw.x,nw.y) && mp[a.x+dx2[i]][a.y+dy2[i]]!='X' && mp[nw.x][nw.y] != 'X' && !vis[nw.x][nw.y]){
                q.push(nw);
                vis[nw.x][nw.y] = vis[a.x][a.y] + 1;
                //cout<<nw.x<<' '<<nw.y<<' '<<vis[nw.x][nw.y]<<'\n';
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(vis[i][j])cout<<vis[i][j]-1<<" \n"[j==m];
            else cout<<"-1"<<" \n"[j==m];
        }
    }
    return 0;
}

M. 自闭

模拟。


Code

#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define G0(x) memset(x,0,sizeof(x))
#define MAXN 107
bool sub[MAXN];
bool ac[MAXN][17];
int acc[MAXN];
int was[MAXN][17];
int wac[MAXN][17];
int accnt[17];
int zb[MAXN];
int n,m,W;
int main() {
    scanf("%d%d%d", &n, &m, &W);
    G0(sub),G0(ac),G0(was),G0(wac),G0(accnt),G0(zb),G0(acc);
    REP(i,0,W) {
        int x,y,c; scanf("%d%d%d", &x, &y, &c); x--,y--;
        sub[x]=1;
        if(c) {
            if(!ac[x][y]) accnt[y]++,ac[x][y]=1,acc[x]++;
            wac[x][y]=0;
        } else {
            wac[x][y]++;
            was[x][y]=max(was[x][y],wac[x][y]);
        }
    }
    REP(i,0,n) {
        if(!sub[i]) {
            zb[i]=998244353;
            continue;
        } else if(!acc[i]) {
            zb[i]=1000000;
            continue;
        } else if(acc[i]==m) {
            zb[i]=0;
            continue;
        }
        REP(j,0,m) {
            if(!ac[i][j] && accnt[j]>0) {
                zb[i]+=20;
            }
            if(!ac[i][j] && accnt[j]>=n/2) {
                zb[i]+=10;
            }
            zb[i]+=was[i][j]*was[i][j]*((!ac[i][j])+1);
        }
    }
    REP(i,0,n) {
        printf("%d\n", zb[i]);
    }
    
}

N. 合并!

稍微手模一下就可以发现怎么合并答案都是一样。


Code

/*
 * Author:  heyuhhh
 * Created Time:  2020/1/17 13:05:18
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2000 + 5;

int n;
int a[N];

void run(){
    for(int i = 1; i <= n; i++) cin >> a[i];
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n; j++) {
            ans += a[i] * a[j];
        }
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/heyuhhh/p/12323341.html