牛课多校第三场A.C.H

又一次成功的签到了(大哭~~~~~~)只做了2题然后就一直挂机了,会的慢慢补吧。

A PACM Team

好吧,从一开始就看错了题目,这是一个四维背包问题(贴的别人的代码了)

#include <cstdio>
#include <iostream>
#define N 40
using namespace std;
int n, P, A, C, M, p[N], a[N], c[N], m[N], g[N], f[N][N][N][N];
//f数组记录p,a,c,m人数有N,N,N,N人时的最大取值 
bool h[N][N][N][N][N];//记录路径 
int main()
{
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> p[i] >> a[i] >> c[i] >> m[i] >> g[i];
    cin >> P >> A >> C >> M;
  for(int i = 1; i <= n; i++)
        for(int jp = P; jp >= p[i]; jp --)
            for(int ja = A; ja >= a[i]; ja --)
                for(int jc = C; jc >= c[i]; jc --)
                    for(int jm = M; jm >= m[i]; jm --)
                        if (f[jp - p[i]][ja - a[i]][jc - c[i]][jm - m[i]] + g[i] > f[jp][ja][jc][jm])
                        {
                            f[jp][ja][jc][jm] = f[jp - p[i]][ja - a[i]][jc - c[i]][jm - m[i]] + g[i];
                            h[i][jp][ja][jc][jm] = 1;
                        }
    int ans[N];
    ans[0] = 0;
    for(int i = n; i >= 1; i --)//恢复路径 即取的队伍 
        if (h[i][P][A][C][M])
        {
            ans[++ ans[0]] = i - 1;
            P -= p[i];
            A -= a[i];
            C -= c[i];
            M -= m[i];
        }
    cout << ans[0] << endl;
    for(int i = 1; i <= ans[0]; i ++) cout << ans[i] << endl;
    return 0;
}

C Shuffle Cards

rope大法好啊,stl大法好啊,不过还是得去学习一下splay啊

贴一个rope 不了解的可以戳一下https://blog.csdn.net/iamzky/article/details/38348653

#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
 
int n,m;
int a,b;
rope<int> R;
 
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) R.push_back(i);
    for(int i = 0; i < m; i++){
        scanf("%d%d", &a, &b);
        R = R.substr(a-1, b) + R.substr(0, a-1) + R.substr(a+b-1, n-a-b+1);
    }
    for(int i = 0; i < n; i++) printf("%d ", R[i]);
}

splay代码:

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 300000 + 10;
const int INF = 0x3f3f3f3f;

int n, root, ch[maxn][2], s[maxn], v[maxn];
bool rev[maxn];

#define lc ch[o][0]
#define rc ch[o][1]


void maintain(int o) { 
	s[o] = s[lc] + s[rc] + 1; 
}

void rotate(int& o, int d) 
{ 
	int k = ch[o][d^1]; ch[o][d^1] = ch[k][d]; ch[k][d] = o; 
	maintain(o); maintain(k); o = k;
}

void pushdown(int o) 
{ 
	rev[o] ^= 1; 
	rev[lc] ^= 1; 
	rev[rc] ^= 1; 
	swap(lc, rc); 
}

int cmp(int o, int k) 
{ 
	if(s[lc] + 1 == k) return -1; 
	return k < s[lc] + 1 ? 0 : 1; 
}

void splay(int& o, int k) 
{
	if(rev[o]) pushdown(o); //notice
	int d = cmp(o, k);
	if(d == -1) return;
	if(d == 1) k -= s[lc] + 1;
	int p = ch[o][d];
	if(rev[p]) pushdown(p); //notice
	int d2 = cmp(p, k);
	int k2 = (d2 == 0) ? k : k-s[ch[p][0]]-1;
	if(d2 != -1) {
		splay(ch[p][d2], k2);
		if(d == d2) rotate(o, d^1); else rotate(ch[o][d], d);
	}
	rotate(o, d^1);
}

void rever(int& o, int L, int R) 
{ 
	splay(o, L); 
	splay(rc, R - s[lc] + 1); //R+2 - (s[lc]+1)
	rev[ch[rc][0]] ^= 1; 
}

void build(int L, int R, int p, int d) 
{
	int cur;
	if(L == R) cur = L;
	else {
		cur = (L + R) >> 1;
		if(L <= cur - 1) build(L, cur - 1, cur, 0); 
		if(cur + 1 <= R) build(cur + 1, R, cur, 1);
	}
	maintain(cur);
	ch[p][d] = cur;
}

void print(int o) 
{
	if(rev[o]) pushdown(o);
	
	if(lc) print(lc);
	if(v[o] != INF) printf("%d ", v[o]);
	if(rc) print(rc);
}

int main() {
	int m;
	scanf("%d%d", &n, &m);
	v[1] = v[n + 2] = INF;
	for(int i = 1; i <= n; i++) v[i + 1] = i;
	
	build(1, n + 2, 0, 0); 
	root = (n + 3) >> 1;

	for(int i = 1; i <= m; i++) {
		int l, len;
		scanf("%d %d", &l, &len);
		rever(root, 1,l+len-1);
		rever(root,1,len);
		rever(root,len+1,l+len-1);
	}
	print(root);
	return 0;
}

用三次区间翻转,解决平移,不懂得画个图,举个栗子就行了。

H Diff-prime Pairs

  =k1(素数)                =k2(素数)

相除得到 i/j=k1/k2     当i和j同时乘以一个数t时也是满足这个等式,可知ti 与 tj也是满足条件的一个数对

所以当我们找到两个在1~n 范围内的素数a,b时,他们的倍数也是满足条件的,那么有几对呢,对数的个数当然是由数值较大的决定,就是n/max(a,b);

思路:先求出所给1~n的所有素数 存入数组(2,3,5,7.......)

第一个素数2前面时没有和他配对的,那就从3开始。当算到第i个素数temp时,计算出1~n是temp倍数的个数,然后再乘以temp前面素数的个数(比temp小的素数肯定可以找到和temp相同倍数的数的)。最后不要忘记*2,此题就ok了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAX 10000005
int prime[MAX];//存放素数 
bool check[MAX];//判断是不是素数 0为不是素数 
int solve(int n){
	int count;
	memset(check, 0, sizeof(check));
        count=0;
        for (int i = 2; i <= n; i++)
        {
            if (!check[i])
                prime[count++] = i;
            for (int j = 0; j < count; j++)
            {
                if (i*prime[j] > MAX)
                    break; // 过大的时候跳出
                check[i*prime[j]] = 1;
                if ((i%prime[j]) == 0) // 如果i是一个合数,而且i % prime[j] == 0
                    break; 
            }
            
        }
	return count;
}
int main()
{
	int n;
	while(cin>>n)
	{
		int all=solve(n);//素数的个数 
		ll res=0;
		for(int i=1;i<all;++i){
			int temp=n/prime[i];//计算出1~n是prime[i]倍数的个数 
			res+=temp*i;//乘以出现在prime[i]前面素数的个数 
		}
		cout<<res*2<<endl;//(x,y)和(y,x)算两种 所以乘以2 
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/TDD_Master/article/details/81222202