CCPC2018-湖南全国邀请赛

传送门

A - Easy \(h\)-index

签到。

Code

/*
 * Author:  heyuhhh
 * Created Time:  2019/10/29 11:58:23
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
const int MAXN = 2e5+5;
typedef long long ll;
int n,a[MAXN];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin>>n){
        for(int i=0;i<=n;i++)cin>>a[i];
        int ans = 0;
        ll sum1=0,sum2=0;
        for(int i=n;i>=1;i--){
            sum1+=a[i];
            if(sum1 >= i)ans=max(ans,i);
        }
        cout<<ans<<'\n';
    }
    return 0;
}

B - Higher \(h\)-index

题意:
定义\(h\)指数为现在至少有\(h\)篇论文,它的被引用次数至少为\(h\)。
现在你要开始写论文,若在一篇论文上花\(x\)小时,则会被引用\(a\cdot x\)次;同时,写一篇论文的时候,也可以引用之前自己写过的论文。
现在共有\(n\)小时来分配写论文,问最大的\(h\)指数为多少。

思路:
被这个题卡了两个小时...二分思路其实很早就有了,但是细节没有考虑清楚。

  • 显然\(h\)指数具有单调性,故二分\(h\),那么我们接下来就是判断\(n\)个小时能否通过合理的分配,最终满足\(h\)指数。
  • 首先肯定要写\(h\)篇论文,并且每篇尽可能应用前面的文章,那么最后得到的引用序列就为:\(a+h-1,a+h-2,\cdots,a\)。
  • 注意到这个值是连续下降的,观察发现我们每次多花一个小时写一篇新论文,则\(1\)到\(h\)号论文中至多有一篇的引用次数会增加到\(h\),等价于在这篇论文上多花一个小时来达到目标。
  • 所以策略就是判断\(a\)和\(h\)的大小关系,若\(h<a\),那么就在后面新写\(a-h\)篇论文即可。

代码很短:

Code

/*
 * Author:  heyuhhh
 * Created Time:  2019/11/3 11:29:12
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
int n,a;

bool chk(int h) {
    ll t = h;
    if(h > a) {
        t += h - a;
    }
    return t <= n;
}

void run() {
    int l = 0, r = n + 1, mid;
    while(l < r) {
       int mid = (l + r) >> 1;
       if(chk(mid)) l = mid + 1;
       else r = mid;
    }
    cout << l - 1 << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin>>n>>a) run();
    return 0;
}

C - Just \(h\)-index

似乎是个主席树裸题...

Code

#include<bits/stdc++.h>
#define mid l+((r-l)>>1)
const int MAXN = 1e5+5;
using namespace std;
int n,q,a[MAXN],tot,rt[MAXN],sz[MAXN*20],lc[MAXN*20],rc[MAXN*20];

void build(int *o,int l,int r){
    *o = ++tot;
    sz[*o] = 0;
    if(l==r)return ;
    int m=mid;
    build(&lc[*o],l,m);build(&rc[*o],m+1,r);
}
void insert(int *o,int u,int v){
    int l=1,r=n,m;
    while(l!=r){
       m=mid;
       sz[*o=++tot] = sz[u] + 1;
       if(v<=m)rc[*o]=rc[u],o=&lc[*o],u=lc[u],r=m;
       else lc[*o]=lc[u],o=&rc[*o],u=rc[u],l=m+1;
    }
    sz[*o=++tot] = sz[u]+1;
}

int query(int u,int o,int l,int r,int sum){
    if(l==r)return l;
    int m = mid;
    int s = sz[rc[o]] - sz[rc[u]];
    if(sum + s >= m+1)return query(rc[u],rc[o],m+1,r,sum);
    else{
        return query(lc[u],lc[o],l,m,sum + s);
    }
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    while(cin>>n>>q){
        for(int i=1;i<=n;i++)cin>>a[i];
        tot=0;
        build(&rt[0],1,n);
        for(int i=1;i<=n;i++){
            insert(&rt[i],rt[i-1],a[i]);
        }
        while(q--){
            static int l,r;
            cin>>l>>r;
            cout<<query(rt[l-1],rt[r],1,n,0)<<'\n';
        }
    }
    return 0;
}

F - Sorting

直接按规则排序即可,因为涉及到分数,通分又会爆long long,所以手写一个分数类。但这还不够,最后比较分数的大小的时候辗转相除一下即可。复杂度多个\(logn\).

Code

/*
 * Author:  heyuhhh
 * Created Time:  2019/10/29 11:58:23
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
const int MAXN = 2e5+5;
typedef long long ll;
typedef unsigned long long ull;
int n;
inline int cmp(ull a,ull b,ull c,ull d){
    if(a/b == c/d){
        if(a%b==0&&c%d==0)return 0;
        else if(a%b==0 && c%d!=0)return -1;
        else if(a%b!=0 && c%d==0)return 1;
        return -cmp(b,a%b,d,c%d);
    }
    else{
        return a/b < c/d?-1:1;
    }
}
struct frac{
    ull x,y;
    int id;
    bool operator <(const frac&rhs)const{
        int d = cmp(x,y,rhs.x,rhs.y);
        if(d==0)return id<rhs.id;
        else{
            return d==-1?true:false;
        }
    }
}a[MAXN];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin>>n){
        ull x,y,z;
        for(int i=1;i<=n;i++){
            cin>>x>>y>>z;
            a[i].x = (x+y);
            a[i].y = (x+y+z);
            a[i].id = i;
        }
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)cout<<a[i].id<<" \n"[i==n];
    }
    return 0;
}

G - String Transformation

题意:
给出只由\(a,b,c\)构成的\(S\)串和\(T\)串,现在有三种特殊的串\(aa,bb,abab\),可以在\(S\)串中任意插入或者删除,问最后能否变为\(T\)串。

思路:

  • 因为特殊字符串不涉及\(c\),所以相当于\(c\)为分隔符,现在只用考虑全由\(a,b\)构成的两个字符串是否相等。
  • 注意一个特殊的东西:\(ab\)可以变为\(ba\),\(ba\)也可以变为\(ab\)。
  • 那么可以大力猜测最终倘若把字符串化为最简,是由很少的几个字符构成。
  • 因为无论删除\(aa,bb\)还是\(abab\),\(a,b\)个数的奇偶性不会发生改变,那么我们直接根据两个串的\(a,b\)奇偶性来判断就行。
  • 正确性:假设我们全都删掉连续的相同的,并且把一些连续的\(abab\)删掉,显然最后只有可能是\(aba,\emptyset,a,b,ab\)这几种情况,然后就可以发现与奇偶性相关了。

代码如下:

Code

/*
 * Author:  heyuhhh
 * Created Time:  2019/11/3 11:29:12
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e4 + 5;

int n, m;
char s[N], t[N];

void run(){
    n = strlen(s + 1), m = strlen(t + 1);
    int c1 = 0, c2 = 0;
    for(int i = 1; i <= n; i++) c1 += (s[i] == 'c');
    for(int i = 1; i <= m; i++) c2 += (t[i] == 'c');
    if(c1 != c2) {
        cout << "No" << '\n';
        return;
    }
    int i = 1, j = 1;
    int s_a = 0, s_b = 0, t_a = 0, t_b = 0;
    while(i <= n || j <= m) {
        while(i <= n && s[i] != 'c') {
            if(s[i] == 'a') ++s_a;
            else ++s_b;
            ++i;
        }
        while(j <= m && t[j] != 'c') {
            if(t[j] == 'a') ++t_a;
            else ++t_b;
            ++j;
        }
        ++i, ++j;
        if(((s_a & 1) == (t_a & 1)) && ((s_b & 1) == (t_b & 1))) {
            s_a = s_b = t_a = t_b = 0;
        }
        else {
            cout << "No" << '\n';
            return;
        }
    }
    cout << "Yes" << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> (s + 1) >> (t + 1)) run();
    return 0;
}

J - Vertex Cover

题意:
给出一个完全图,第\(i\)个点的权值为\(2^i\)。
询问有多少种选边方式,使得覆盖这些边的点集之和为\(k\)(给出其二进制表示)。
定义覆盖一条边即为这条边的两个端点至少有一个点被选中。
同时,选择点去覆盖边时,尽量选择权值之和较小的点。也就是说,对于一条边的两个点,只选择权值较小的那一个点即可,不选择另一端点(假设图中只有这一条边)。

思路:

  • 按二进制位从高到底考虑:
  • 假设当前为\(1\),设前面有\(a\)个\(1\),\(b\)个\(0\),那么方案数为\((2^b-1)\cdot 2^a\),表示至少连向一个\(0\),同时可以任意连向\(1\),这样可以保证这个\(1\)必选;
  • 如果当前为\(0\),方案数为\(2^a\),表示可以随便连向前面的\(1\),因为前面的\(1\)必选,所以这个\(0\)必然不会选。
  • 然后就没了。

代码如下:

Code

/*
 * Author:  heyuhhh
 * Created Time:  2019/11/3 11:29:12
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MOD = 1e9+7,MAXN=1e5+5;
//head
int n,pw[MAXN];
char s[MAXN],t[MAXN];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    pw[0]=1;
    for(int i=1;i<=100000;i++)pw[i] = pw[i-1]*2%MOD;
    while(cin>>n){
        cin>>t;
        int len =strlen(t);
        for(int i=0;i<n-len;i++)s[i]='0';
        for(int i=0;i<len;i++)s[n-len+i] = t[i];
        int cnt=0;
        ll ans=1;
        for(int i=0;i<n;i++){
            if(s[i]=='1')ans = ans*((pw[i-cnt]-1+MOD)%MOD)%MOD*pw[cnt]%MOD;
            else ans=ans*pw[cnt]%MOD;
            if(s[i]=='1')cnt++;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

K - 2018

题意:
给出\(a,b,c,d\),问有多少对\((x,y)\),满足\(a\leq x\leq b,c\leq y\leq d\),且\(x\cdot y|2018\)。

思路:
分情况讨论即可:

  • \(x\)为\(1009\)的奇数倍;
  • \(x\)为\(1009\)的偶数倍;
  • \(x\)为偶数且不为\(1009\)的倍数;
  • \(x\)为奇数且不为\(1009\)的倍数。

这样就能覆盖所有情况了。

Code

/*
 * Author:  heyuhhh
 * Created Time:  2019/10/29 11:58:23
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
const int MAXN = 2e5+5;
typedef long long ll;
ll a,b,c,d;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin>>a>>b>>c>>d){
        ll ans=0;
        ans += (b/2018 -(a-1)/2018) * (d-c+1);
        ans += ((b/1009 - (a-1)/1009) - (b/2018 - (a-1)/2018)) * (d/2 -(c-1)/2);
        ans += (b/2 - (a-1)/2 - (b/2018 - (a-1)/2018)) * (d/1009 - (c-1)/1009);
        ans += (b-a+1 - (b/2 - (a-1)/2) - ((b/1009 - (a-1)/1009) - (b/2018 - (a-1)/2018))) * (d/2018 - (c-1)/2018);
        cout<<ans<<'\n';
    }
    return 0;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/11789249.html

时间: 2024-10-16 16:33:45

CCPC2018-湖南全国邀请赛的相关文章

hdu - 6276,2018CCPC湖南全国邀请赛A题,水题,二分

题意: 求H的最大值,  H是指存在H篇论文,这H篇被引用的次数都大于等于H次. 思路:题意得,  最多只有N遍论文,所以H的最大值为N, 常识得知H的最小值为0. 所以H的答案在[0,N]之间,二分搜一下,如果满足就提高下限,不满足则降低上限. 嗯就这样!!!! AC code: #include<bits/stdc++.h> using namespace std; int n; vector<int> cc(200005); int main() { bool check(i

2013ACM-ICPC杭州赛区全国邀请赛——Random Walk

题目链接 题意: n个点,按照题中给的公式可以求出任意两个点转移的概率.求从1到n的期望转移次数 分析: 设dp[i]为从i到n的期望,那么可以得到公式dp[i] = sigma(dp[i + j] * p(i + j, i)),1 <= j <= m 把这个式子展开来:dp[i - m] * p(i - m, i) + dp[i - m + 1] * dp(i - m + 1, i) + ... + dp[i] * p(i, i) + ... + dp[i + m] * p(i + m, i

2013 ACM-ICPC长沙赛区全国邀请赛——Travel in time

题目链接 题意: 给n个点,m条边的无向图,一个起点和一个终点.每边都有消耗,经过就要付出代价:每个点有消耗和价值,只有消耗了才会获得价值,如果不消耗就不会获得价值,且下一次消耗的点的价值一定要严格大于之前消耗过的点的价值 求:起点到终点消耗不超过给定值T时的价值最大值 1 < N < 100,0 < M < 1000,0 < T <= 300 分析: 对于不进行点的消耗的操作,就是求两点的最短路,floyd求 表示一下状态: 可以粗率表示为:当前所在点.总消耗值.总价

2013 ACM-ICPC南京赛区全国邀请赛

题目链接:http://acm.hdu.edu.cn/search.php?field=problem&key=2013 ACM-ICPC南京赛区全国邀请赛--题目重现&source=1&searchmode=source A(HDU4586) Play the Dice Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1

HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4573 Problem Description Remember our childhood? A few naked children throw stones standing on the same position, the one throws farther win the game. Aha, of course, there are some naughty boys who care

2014湘潭全国邀请赛I题 Intervals /POJ 3680 / 在限制次数下取有权区间使权最大/小问题(费用流)

先说POJ3680:给n个有权(权<10w)开区间(n<200),(区间最多数到10w)保证数轴上所有数最多被覆盖k次的情况下要求总权最大,输出最大权. 思路:       限制的处理:s-->开始流量为k,要求总权最大,即费用最大,所以费用取负,最小费用最大流即可.对于输入区间[a,b]:w,添加边:a-->b,流量为1,费用为-w. 对于点i,i+1,添加边,费用为0,流量无穷.显然这种处理,限制了区间最多取k次,(流量控制),跑最大流能走添加的边尽量走,且越大越好(负数刚刚是

CCPC2018-湖南全国邀请赛 G String Transformation

String Transformation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 36    Accepted Submission(s): 8 Problem Description Bobo has a string S=s1s2-sn consists of letter `a`, `b` and `c`.He can t

2014上海全国邀请赛题解 HDOJ 5090-5099

HDOJ 5090 水题,从小到大排序,可以填充达到符合条件的,先填充好,填充之后进行调整. 传送门:点击打开链接 #include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int

2014西安全国邀请赛

D - Wow! Such String!: 这道字符串题居然正解是欧拉图,我也是看醉了...欧拉图虽然学过,但可能理解得还不是很深,所以对这种题不敏感. 这道题解法是把每四个字符组成的字符串看成是一个点,每个点有26个入边和26个出边,可以证明这是一个欧拉图.然后遍历找一下欧拉图就行了. 不过...一开始我是自己建了个图...结果超内存...然后想打表...结果根本不让我交...实在无奈,改成了每个点自己找下一个点,不连边.(现在想想连边好像是没有必要的)另,看题的时候还是要仔细看题目要求,尽

哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练. 题解: E666 这个题是让求有多少个子串只含有6.寻找连续的6,然后用n*(n+1)/2求出这一段的子串个数,然后把每一段连续的加起来. 做的时候wa了很多次,原来是在n*(n+1)的地方已经超过int型了,所以需要设置类型为long long. #include <cstdio> #inc