2018 CCPC FINAL
kunkun全球后援队训练赛赛
A.
签到
笨比mwh wa了两发

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int t, n, m, kas;
struct node{
int d, t;
}list[N];
bool cmp(node a, node b){
if (a.d == b.d) return a.t < b.t;
return a.d < b.d;
}
int main()
{
// cin.tie(0);
// cout.tie(0);
// ios::sync_with_stdio(0);
cin >> t;
kas = 0;
while (t--)
{
cin >> n >> m;
for (int i = 0; i < n; ++i)
cin >> list[i].d;
for (int i = 0; i < n; ++i)
cin >> list[i].t;
sort(list, list + n, cmp);
int ans = 0;
int x = 0;
for (int i = 0; i < n; ++i)
{
x += list[i].t;
if (x <= m)
ans++;
else
break;
}
printf("Case %d: %d\n", ++kas, ans);
}
}
L
数学 思维
看了样例,一开始的想法是把这个数字先除以6,然后再找。(当然找不到了)
然后发现题目给了条件
A weaker version of this conjecture states that every odd number greater than 5 is the sum of three prime numbers.
顺其自然的就想到解法
先找到比n小且和n的差大于等于11的最大素数tmp (tmp就是要找的6个素数中的一个), 得到 n - tmp , 如果 n - tmp 是奇数, 就把它减去4, 输出 2 2,如果 n - tmp 是偶数, 就把它减去5, 输出 2 3。由于题目给出的结论, 剩下的数是肯定可以由3个素数组成的。因为我们之前减的tmp是最大的满足条件的素数,所以剩余的素数应该非常小,可以直接暴力。

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define REP(i,k,n) for(int i=k;i<=n;i++)
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
int t, ind;
ll n;
const int N = 1e5 + 5;
int prime[10000010],book[10000010];
void turn(int p)
{
for(int i = 2; i <= p; i++)
{
if(!book[i]) prime[++ind]=i;//如果没有筛过,记录素数
REP(j,1,ind){//其中记录数组里的素数保证严格递增
if(i*prime[j]>p) break;//保证小于n,要不然没有意义
book[i*prime[j]]=1;//筛去这个合数
if(!i%prime[j]) break;//如果>=这个数的最小质因子,那就结束
}
}
}
bool check(ll n){
ll tmp = sqrt(n);
for (int i = 2; i <= tmp; ++i)
if (n % i == 0)
return false;
return true;
}
int main()
{
turn(100000);
cin >> t;
int kas = 0;
while (t--)
{
scanf("%lld", &n);
if (n == 12)
{
printf("Case %d: 2 2 2 2 2 2\n", ++kas);
continue;
}
ll tmp;
if (n <= 11)
{
printf("Case %d: IMPOSSIBLE\n", ++kas);
continue;
}
for (ll i = n - 11; i >= 0; --i)
{
if (check(i))
{
tmp = i;
break;
}
}
n = n - tmp;
int flag;
if (n & 1)
{
n -= 4;
flag = 1;
}
else
{
n -= 5;
flag = 2;
}
for (ll i = 1; i <= 9592; ++i)
{
for (ll j = 1; j <= 9592; ++j)
{
if (check(n - prime[i] - prime[j]) && n - prime[i] - prime[j] > 0)
{
if (flag == 1)
{
printf("Case %d: 2 2 %lld %d %d %d\n", ++kas, tmp, prime[i], prime[j], n - prime[i] - prime[j]);
flag = -1;
break;
}
else
{
printf("Case %d: 2 3 %lld %d %d %d\n", ++kas, tmp, prime[i], prime[j], n - prime[i] - prime[j]);
flag = -1;
break;
}
}
}
if (flag == -1)
break;
}
}
}
G
找规律 逆元
直接dfs搜
打表程序找出规律,推出公式,注意mod的时候要逆元

#include <cstdio>
#include <cmath>
#include <algorithm>
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
ll t, m, n;
ll solve(ll n) {
return n * (n + 1) / 2;
}
ll quick_m(ll a, ll x) {
ll ans =1;
while (x) {
if (x&1) {
ans = ans * a % mod;
}
x>>=1;
a = a * a % mod;
}
return ans;
}
int main () {
scanf("%d", &t);
int kas = 0;
while (t--) {
scanf("%lld%lld", &n, &m);
if (n < 3 || m < 3) {
printf("Case %d: %d\n", ++kas, 0);
continue;
} else if (m == 3 && n == 3) {
printf("Case %d: %d\n", ++kas, 1);
continue;
} else if (n > 7 && m > 7) {
ll ans = 1;
// n--;
// m--;
ans = ans * m % mod;
ans = ans * (m-1) % mod;
ans = ans * (m-2) % mod;
ans = ans * (m+1) % mod;
// ans = ans * a[n] % mod;
ans = ans * quick_m(24, mod-2) % mod;
ans = ans * n % mod;
ans = ans * (n-1) % mod;
ans = ans * (n-2) % mod;
ans = ans * (n+1) % mod;
// ans = ans * a[m] % mod;
ans = ans * quick_m(24, mod-2) % mod;
printf("Case %d: %lld\n", ++kas, ans);
} else {
n -= 2;
m -= 2;
ll ans1 = 0, ans2 = 0;
for (ll i = 1; i <= n; i++) {
ans1 = (ans1 + solve(i) * (n-i+1)) % mod;
}
for (ll j = 1; j <= m; j++) {
ans2 = (ans2 + solve(j) * (m-j+1)) % mod;
}
printf("Case %d: %lld\n", ++kas, ans1*ans2 % mod);
}
}
return 0;
}
L
没打出来
等待补提,贴一个隔壁队大神的代码

//zyh
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int numx[N], numy[N], connumy[N], connumx[N];
vector <int> vex, vey;
set <int> st[N];
struct node{
int x, y;
}a[N];
int newyid[N], newxid[N];
bool cmpy(int x, int y)
{
return numy[x] > numy[y];
}
bool cmpx(int x, int y)
{
return numx[x] > numx[y];
}
set <int> :: iterator it;
int main()
{
// freopen("1.txt", "r", stdin);
int T, n, ca=0, x, y;
scanf("%d", &T);
while(T--)
{
memset(numx, 0, sizeof(numx));
memset(numy, 0, sizeof(numy));
memset(connumy, 0, sizeof(connumy));
memset(connumx, 0, sizeof(connumx));
scanf("%d", &n);
for(int i = 1; i <= n; i++) st[i].clear();
vex.clear(); vey.clear();
for(int i = 1; i <= n; i++)
{
scanf("%d %d", &a[i].x, &a[i].y);
vex.push_back(a[i].x);
vey.push_back(a[i].y);
}
sort(vex.begin(), vex.end());
vex.erase(unique(vex.begin(), vex.end()), vex.end());
sort(vey.begin(), vey.end());
vey.erase(unique(vey.begin(), vey.end()), vey.end());
for(int i = 1; i <= n; i++)
{
x = lower_bound(vex.begin(), vex.end(), a[i].x)-vex.begin()+1;
y = lower_bound(vey.begin(), vey.end(), a[i].y)-vey.begin()+1;
numx[x]++;
connumx[x]++;
numy[y]++;
connumy[y]++;
st[x].insert(y);
}
int sizey = vey.size(), sizex = vex.size();
for(int i = 1; i <= sizey; i++) newyid[i] = i;
for(int i = 1; i <= sizex; i++) newxid[i] = i;
sort(newyid+1, newyid+1+sizey, cmpy);
sort(newxid+1, newxid+1+sizex, cmpx);
sort(numx+1, numx+1+sizex, greater<int>());
sort(numy+1, numy+1+sizey, greater<int>());
ll res = 0, num = 0;
for(int i = 1; i <= sizex; i++)
{
if(numx[i]+numy[1] <= res) continue;
for(int j = 1; j <= sizey; j++)
{
int tmp = st[newxid[i]].count(newyid[j]);
if(numx[i]+numy[j]-tmp>res)
res = numx[i]+numy[j]-tmp;
if(tmp == 0) break;
}
}
for(int i = 1; i <= n; i++)
{
x = lower_bound(vex.begin(), vex.end(), a[i].x)-vex.begin()+1;
y = lower_bound(vey.begin(), vey.end(), a[i].y)-vey.begin()+1;
if(connumx[x]+connumy[y]==res+1)
num++;
}
for(int i = 1; i <= sizex; i++)
{
int s = lower_bound(numy+1, numy+1+sizey, res-numx[i], greater<int>()) - numy;
int e = upper_bound(numy+1, numy+1+sizey, res-numx[i], greater<int>()) - numy - 1;
int tmp = e - s + 1;
for(it = st[newxid[i]].begin(); it != st[newxid[i]].end(); it++)
{
if(connumy[*it]==res-numx[i]) tmp--;
}
num += tmp;
}
if(res==2) num /= 2;
printf("Case %d: %lld %lld\n", ++ca, res, num);
}
}
膜yh大神 ORZ
