2018 ccpc final

 

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);
    }
}
View Code

 

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;
        }
        
    }
}
View Code

 

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;
}
View Code

 

正解

题目意思可以理解为寻找i两个子矩阵,推出公式 () 

https://blog.csdn.net/Tony5t4rk/article/details/88054604?tdsourcetag=s_pctim_aiomsg

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;

ll C[maxn][5];

void Init() {
    C[0][0] = 1;
    for (int i = 1; i < maxn; ++i) {
        C[i][0] = 1;
        for (int j = 1; j < 5; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    Init();
    int t; cin >> t;
    for (int Case = 1; Case <= t; ++Case) {
        int n, m; cin >> n >> m;
        if (n < 3 || m < 3) {
            cout << "Case " << Case << ": " << 0 << endl;
            continue;
        }
        cout << "Case " << Case << ": " << ((C[n][3] + C[n][4]) % mod) * ((C[m][3] + C[m][4]) % mod) % mod << endl;
    }
    return 0;
}
View Code

 

 

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);
    }    
}
View Code

膜yh大神 ORZ

posted @ 2019-10-13 18:32  violet72  阅读(414)  评论(0编辑  收藏  举报