又一次成功的签到了(大哭~~~~~~)只做了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;
}