2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)

22 篇文章 0 订阅
14 篇文章 0 订阅

链接

A 分组

待补

B 二进制

队友写的

#include "bits/stdc++.h"
using namespace std;
typedef long long ll;

const int maxn = 1e5 + 5;

#define debug(x) cout << #x << ":" << x << endl;
#define mst(x, a) memset(x, a, sizeof(x))
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)

int n, m;
struct Node {
    int l, r;
    ll s, lz;
} t[14][maxn << 2];
void push_up(int root, int st) {
    t[root][st].s = t[root][st * 2].s + t[root][st * 2 + 1].s;
}
void push_down(int root, int st) {
    ll lz = t[root][st].lz;
    if (lz == 0)
        return;
    t[root][st].lz = 0;
    t[root][st * 2].lz += lz;
    t[root][st * 2 + 1].lz += lz;

    t[root][st * 2].s += (t[root][st * 2].r - t[root][st * 2].l + 1) * lz;
    t[root][st * 2 + 1].s += (t[root][st * 2 + 1].r - t[root][st * 2 + 1].l + 1) * lz;
}
void build(int root, int st, int l, int r) {
    t[root][st].l = l, t[root][st].r = r;
    if (l == r) {
        t[root][st].s = t[root][st].lz = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(root, st * 2, l, mid);
    build(root, st * 2 + 1, mid + 1, r);
    push_up(root, st);
}
void update(int root, int st, int l, int r, int ql, int qr, ll num) {
    if (ql <= l && qr >= r) {
        t[root][st].lz += num;
        t[root][st].s += 1ll * (r - l + 1) * num;
        return;
    }
    push_down(root, st);
    int mid = (l + r) >> 1;
    if (ql <= mid)
        update(root, st * 2, l, mid, ql, qr, num);
    if (qr > mid)
        update(root, st * 2 + 1, mid + 1, r, ql, qr, num);
    push_up(root, st);
}
ll query(int root, int st, int l, int r, int ql, int qr) {
    if (ql <= l && qr >= r)
        return t[root][st].s;
    push_down(root, st);
    int mid = (l + r) >> 1;
    ll ans = 0;
    if (ql <= mid)
        ans += query(root, st * 2, l, mid, ql, qr);
    if (qr > mid)
        ans += query(root, st * 2 + 1, mid + 1, r, ql, qr);
  //  push_up(root, st);
  	return ans;
}
int main() {
    scanf("%d%d", &n, &m);
    rep(i,0,12) build(i,1,1,n);
    while (m--) {
        int op, l, r, opp;
        ll k;
        scanf("%d", &opp);
        if (opp == 1) {
            scanf("%d%d%d%lld", &op, &l, &r, &k);
            int root = 1;
            while (op) {
                if(op%2)update(root, 1, 1, n, l, r, k);
                op/=2;
                root++;

            }
        } else {
            ll ans = 0;
            scanf("%d%d%d", &op, &l, &r);
            int root = 1;
            while (op) {
                if(op%2)ans += query(root, 1, 1, n, l, r);
                op/=2;
                root++;
            }
            printf("%lld\n", ans);
        }
    }

    return 0;
}

C 不正方形

队友写的

PLL a[maxn],b[maxn];
map<PLL,ll>mps,mpq;
ll n,m;

struct node{
	PLL p1,p2;
};

double check(node l,PLL p){
	PLL p1=l.p1,p2=l.p2;
	return (p2.y-p1.y)*p.x+(p1.x-p2.x)*p.y+(p2.x*p1.y-p1.x*p2.y);
}

void solve(){
	rep(i,1,n){
		rep(j,i+1,n){
			ll ansl=0,ansr=0;
			node t={a[i],a[j]};
			rep(k,1,m){
				if(check(t,b[k])>0) ansl++;
				else ansr++;
			}
			if(ansl&&ansr){
				puts("YES");return ;
			}
		}
	}
	puts("NO");
}

int main()
{
	n=read,m=read;
	rep(i,1,n){
		a[i].x=read,a[i].y=read;
	}
	rep(i,1,m){
		b[i].x=read,b[i].y=read;
	}
	solve();
	
	
	
	return 0;
}

D 分配颜色

队友写的

#include "bits/stdc++.h"
using namespace std;
typedef long long ll;

const int maxn = 2e5 + 5;

#define debug(x) cout << #x << ":" << x << endl;
#define mst(x, a) memset(x, a, sizeof(x))
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)

ll mod;
ll n, m, p, q, t;

ll dp[4020][4020];
ll c[4020][4020];
void init()
{
	int N = 4012;
    c[1][0] = c[1][1] = 1;
    for(int i = 2; i < N; ++ i) {
        c[i][0] = 1;
        for(int j = 1; j < N; ++ j)
            c[i][j] = (1ll * c[i - 1][j] + c[i - 1][j - 1]) % mod;
    }
}


int main() {
    mod = 555555555;
    init();
    scanf("%lld%lld%lld%lld%lld", &n, &m, &p, &q, &t);

    ll ans = 0;

    for (int i = 0; i <= min(n,p); i++) {
        for (int j = 0; j <= min(q,m); j++) {
            ll lan = i * m  + j*n  -i*j*2;
            if (lan != t)
                continue;
            ll d1 = p - i;
            ll d2 = q - j;
            if(d1%2) continue;
            if(d2%2) continue;
            d1 /= 2;
            d2 /= 2;
            ll temp = c[n][i];
            temp%=mod;
            temp = temp*c[m][j]%mod;
            temp%=mod;
            temp = temp * c[d1+n-1][n-1]%mod;
            temp%=mod;
            temp = temp * c[d2+m-1][m-1]%mod;
            temp%=mod;
            
            ans = (ans + temp)%mod;
        	ans = ans%mod;
        }
    }
    printf("%lld", ans);
    return 0;
}

E 土地规划

待补

F CTF

题意: ( 2 i − 1 ) − ( 2 i + 1 − 2 ) (2^{i}-1)-(2^{i+1}-2) (2i1)(2i+12)这里面每个会产生i贡献
分析: 直接模拟写就好了。

/// 欲戴皇冠,必承其重。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#define x first
#define y second
#define sf scanf
#define pf printf
#define PI acos(-1)
#define inf 0x3f3f3f3f
#define lowbit(x) ((-x)&x)
#define mem(a,x) memset(a,x,sizeof(a))
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
#define debug(x) cout << #x << ": " << x << endl;

const int MOD = 998244353;
const int mod = 1e9 + 7;
const int N = 6e5 + 10;
const int dx[] = {0, 1, -1, 0, 0};
const int dy[] = {0, 0, 0, 1, -1};
const int dz[] = {1, -1, 0, 0, 0, 0 };
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

ll n, m;
string str;
ll a[N], b[N];
void solve()
{
    cin>>n;
    ll ans=0;
    for(ll i=1;;i++){
        ll l = (1ll<<i)-1;
        ll r = (1ll<<(i+1))-2;
        if(r>=n){
            r=n;
            ans+=(r-l+1)*i;
            cout<<ans<<endl;
            return ;
        }
        ans+=(r-l+1)*i;    
    }
}
int main()
{
    ll t = 1;
    //scanf("%lld", &t);
    while(t--)
    {
        solve();
    }
    return 0;
}

G 希望

**题意:**给出你A,B了两个树,每个树一共n个节点,然后每个n-1个边,让你求出环长度为m的期望。我们增加一个全排列,让其A连接B数
**分析:**我们看边的话,m长度为环,肯定必须要增加两条边链接A,B。这样m-2我们只要分配这m-2,左右大于等于1满足条件,即可。

我们就得出当m=3时 肯定没有答案为0.
当m=4,我们需要分配2,那么就是左1,右1.

A的两个端点为a,b
B的两个端点为x,y
我们需要连接两个端点, (a-x,b-y)或者(a-y,b-x)两种,这两个节点连接确定,剩下n-2个全排列。
所以答案就是:
( n − 2 ) ! ∗ 2 ∗ A [ 1 ] ∗ B [ 1 ] n ! \frac{(n-2)!*2*A[1]*B[1]}{n!} n!(n2)!2A[1]B[1]
A[1]为边长度1的种类,B[1]为边长度为1的种类。
我们化简一下:
2 ∗ A [ 1 ] ∗ B [ 1 ] n ∗ ( n − 1 ) \frac{2*A[1]*B[1]}{n*(n-1)} n(n1)2A[1]B[1]
这是m=4的情况:
我们再看m=5;同样左右连接,所以(m-2)=3,分解一下为(A1,B2)(A2,B1).
所以我们只需要改下上面式子
2 ∗ ( A [ 1 ] ∗ B [ 2 ] + A [ 2 ] ∗ B [ 1 ] ) n ∗ ( n − 1 ) \frac{2*(A[1]*B[2]+A[2]*B[1])}{n*(n-1)} n(n1)2(A[1]B[2]+A[2]B[1])
同样m=6分成 (A1,B3),(A2,B2),(A3,B1)
然后看m=7分成(A1,B4),(A2,B3),(A3,B2),(A4,B1)

vector<int>ea[310],eb[310];

ll ga[10],gb[10];

ll dep[310];

void bfs1(int s){
	memset(dep,0x3f,sizeof dep);
	queue<int>q;q.push(s);dep[s]=0;
	while(!q.empty()){
		int t=q.front();q.pop();
		for(int i=0;i<ea[t].size();i++){
			int j=ea[t][i];
			if(dep[j]>dep[t]+1){
				dep[j]=dep[t]+1;
				q.push(j);
			}
		}
	}
}

void bfs2(int s){
	memset(dep,0x3f,sizeof dep);
	queue<int>q;q.push(s);dep[s]=0;
	while(!q.empty()){
		int t=q.front();q.pop();
		for(int i=0;i<eb[t].size();i++){
			int j=eb[t][i];
			if(dep[j]>dep[t]+1){
				dep[j]=dep[t]+1;
				q.push(j);
			}
		}
	}
}

int main(){
	
	ll n=read,m=read;
	rep(i,1,n-1){
		int u=read,v=read;
		ea[u].push_back(v);
		ea[v].push_back(u);
	}
	rep(i,1,n-1){
		int u=read,v=read;
		eb[u].push_back(v);
		eb[v].push_back(u);
	}
	rep(i,1,n){
		bfs1(i);
		rep(j,1,n){
			if(dep[j]>0&&dep[j]<=m) ga[dep[j]]++;
		}
	}
	rep(i,1,n){
		bfs2(i);
		rep(j,1,n){
			if(dep[j]>0&&dep[j]<=m) gb[dep[j]]++;
		}
	}
	rep(i,0,9){
		ga[i]/=2;gb[i]/=2;
	//	cout<<i<<" "<<ga[i]<<" "<<gb[i]<<"\n";
	}
	double ans;
	if(m==3) ans=0.0000;
	else if(m==4){
		if(n-1<=0){
			ans=0.0000;
		}
		else ans=2.0*(n-1)*(n-1)/(n*(n-1));
	}
	else if(m==5){
		if(n-1<=0){
			ans=0.0000;
		}
		else 
		ans=2.0*(ga[2]*gb[1]+ga[1]*gb[2])/(n*(n-1));
	}
	else if(m==6){
		if(n-1<=0){
			ans=0.0000;
		}
		else 
		ans=2.0*(ga[2]*gb[2]+ga[1]*gb[3]+ga[3]*gb[1])/(n*(n-1));
	}
	else if(m==7){
		if(n-1<=0){
			ans=0.0000;
		}
		else 
		ans=2.0*(ga[1]*gb[4]+ga[2]*gb[3]+ga[3]*gb[2]+ga[4]*gb[1])/(n*(n-1));
	}
	printf("%.4lf\n",ans);
	return 0;
}

H 只有小A受伤的世界完成了

待补

I 排队队

懒得写了,其实不难,贪心来做。

/// 欲戴皇冠,必承其重。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#define x first
#define y second
#define sf scanf
#define pf printf
#define PI acos(-1)
#define inf 0x3f3f3f3f
#define lowbit(x) ((-x)&x)
#define mem(a,x) memset(a,x,sizeof(a))
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
#define debug(x) cout << #x << ": " << x << endl;

const int MOD = 998244353;
const int mod = 998244353;
const int N = 5e5 + 10;
const int dx[] = {0, 1, -1, 0, 0};
const int dy[] = {0, 0, 0, 1, -1};
const int dz[] = {1, -1, 0, 0, 0, 0 };
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

ll n, m;
string str;
ll ans, sum, b[N];
ll a[N], p[N], q[N];
map<ll, ll>mp;
priority_queue<ll, vector<ll>, greater<ll> > mx[N];
priority_queue<ll, vector<ll>, less<ll> > mi[N];
void solve()
{
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%lld%lld%lld", &a[i], &p[i], &q[i]);
        ll mxx = p[i] - q[i];
        ll mii = min(p[i], q[i]);
        ans += mii;        
        mx[a[i]].push(mxx);        
    }
    sum=0;
    ll tot=0;
    ll res=0;
    priority_queue<ll, vector<ll>, less<ll> > tot1;
    for(int i = 0; i < N; i++)
    {   
        ll flag=0;
        queue<ll> h;
        while(!mx[i].empty())
        {
            ll top=mx[i].top();
            mx[i].pop();
            if(flag==1){
                if(top>=0){
                    ans+=top;
                }else {
                    res-=top;
                    h.push(top);
                }
            }else if(flag==0){
                if(top<=0){
                    ans-=top;
                }
                flag=1;
            }
        }
        ll sz=h.size();
        sum+=sz;
        if(tot<sz){
            sz=tot;
            while(!tot1.empty()){
                tot1.pop();
            }
            while(!h.empty()){
                tot1.push(h.front());
                h.pop();
            }
        }
    }
    if(tot>sum/2){
        ll hh=tot-sum/2;
        while(hh--){
            res+=tot1.top();
            tot1.pop();
        }
    }
    cout<<ans+res<<endl;



}
int main()
{
    ll t = 1;
    //scanf("%lld", &t);
    while(t--)
    {
        solve();
    }
    return 0;
}

J 抽奖

队友做的

int main()
{
	ll x=read;
	ll tmp=x/160;
	ll ans=tmp;
	ll y=tmp/10*3;
	ll now=tmp%10;
	while(1){
		if(y<5) break;
		y=y-5;
		now++;
		if(now%10==0) y=y+3;
		ans++;
	}
	
	
	cout<<ans<<endl; 
	return 0;
}

K 树

待补

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值