2017 CCPC杭州 题解

2017CCPC杭州题目PDF

Problem A. Super-palindrome

题解:

  给你一个字符串,每一步可以将一个字符替换为另一个字符,问你最少多少步可以使得,该字符串任意奇数子串为回文串,偶数子串为回文串。

满足上面条件一定是ababab这种形式,所以我们只要找到数量最多的两种字符用n-numa-numb得到ans1,有可能一种字符的数量过多,这时候我们只要把所有字符都变成这种字符就行了。得到n-numa,ans2;

在ans1和ans2中去最小值就是答案了;

参考代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=210;
int T,a[maxn];
char s[maxn];

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s+1);
        int len=strlen(s+1),ans=0;
        for(int i=1;i<=len;++i) a[i]=s[i]-‘a‘+1;
        for(int i=1;i<=26;++i)
        {
            for(int j=1;j<=26;++j)
            {
                int sum=0;
                for(int k=1;k<=len;++k)
                {
                    if((k&1)&&a[k]==i) ++sum;
                    if(!(k&1)&&a[k]==j) ++sum;
                }
                ans=max(ans,sum);
            }
        }
        for(int i=1;i<=26;++i)
        {
            int sum=0;
            for(int k=1;k<=len;++k)
                if(a[k]==i) sum++;
            ans=max(ans,sum);
        }
        printf("%d\n",len-ans);

    }

    return 0;
}

Problem B. Master of Phi

  公式化简;

参考代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=998244353;
int quick_pow(int a,int b){int ans=1;while(b) {if(b&1) ans=1LL*a*ans%mod;a=1LL*a*a%mod;b>>=1;} return ans;}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m;
        scanf("%d",&m);
        LL ans=1;
        for(int i=1;i<=m;i++)
        {
            int p,q;
            scanf("%d%d",&p,&q);
            ans=1LL*ans*(quick_pow(p,q)+1LL*quick_pow(p,q-1)*(p-1)%mod*q%mod)%mod;
        }
        printf("%lld\n",ans);
    }
}

Problem C. Hakase and Nano

题解:

  给你n对石头,每堆a[i]个,一个d,d==1时表示Hakase先手,d==2时表示Nano先手,每次从一堆中拿任意个石头,至少拿一个;但是这是一个不平等博弈,就是Hakase可以连续拿两次,而Nano只能连续拿一次。问你Hakase是否可以取胜。

  首先如果d==1,那么只有当所有堆石头的数量都为1且数量%3==1的时候Hakase才必败,其他情况都是必胜。

d==2的时候,因为N想赢所以肯定想转换到上述H会输的状态,所以H在n是3的倍数,且有n-1个数为1时会输(这时N只需从不是1的那堆石子里拿掉一些石子使状态变为1 1 1),或者n是3的倍数余1,且n个数为1时会输(此时N只需拿掉一堆石子,H就到了必输态),或者n是3的倍数余1,且n-1个数为1时会输(此时N只需拿掉一堆不是1的石子,H就到了必输态)。

参考代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int T,n,d,x;

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        int cnt=0;
        scanf("%d%d",&n,&d);
        for(int i=1;i<=n;++i) scanf("%d",&x),cnt+=(x==1);
        if(d==1)
        {
            if(cnt==n&&n%3==0) puts("No");
            else puts("Yes");
        }
        else
        {
            if(n%3==1&&cnt>=n-1) puts("No");
            else if(n%3==0&&cnt==n-1) puts("No");
            else puts("Yes");
        }
    }

    return 0;
}

Problem D. Master of Random

题解:

  给你一棵树,每个节点有个权值,现在这个树是随机的,现在随即选择一颗子树,问你这棵子树的节点权值和的期望为多少;

  我们考虑对于一颗子树上面的点,他到子树的根必定在他到整个树的根的路径上面,然后,我们考虑每次添加一个节点,他要么是子树根节点,要么自己单独型号才能一个子树。

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 998244353
typedef long long ll;
const int maxn=1e5+10;
int T,n;
ll num,sum,ans,a[maxn],f[maxn];
ll qpow(ll x,ll y)
{
    ll res=1;
    while(y)
    {
        if(y&1) res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        sum=0;ans=0;
        num=qpow(n,mod-2);
        for(int i=1;i<=n;i++) scanf("%lld",a+i);
        for(int i=1;i<=n;i++)
        {
              f[i]=(sum*qpow(i-1,mod-2)%mod+1)%mod;
              sum=(sum+f[i])%mod;
              ans=(ans+a[i]*f[i]%mod)%mod;
        }
        ans=(ans*num)%mod;

        printf("%lld\n",ans);
    }
      return 0;
}

Problem E. Master of Subgraph

题解:

  题目给你一个树图,然后每个节点一个权值a[i],给你一个m,对于x=1~m :问你该树图里面是否有连通子图的值为x,输出x对应取值下的答案(0/1);

  我们考虑点分治,用bitset维护经过每个点的链的权值和。

参考代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=3e3+10;
const int maxm=1e5+10;
bitset<maxm> bit[maxn],ans;
int T,n,m,w[maxn];
vector<int> g[maxn];
int root,mx[maxn],siz[maxn],S;
bool vis[maxn];

void getroot(int u,int fa)
{
    siz[u]=1;mx[u]=0;
    for(int i=0,len=g[u].size();i<len;++i)
    {
        int v=g[u][i];
        if(v==fa || vis[v]) continue;
        getroot(v,u);
        siz[u]+=siz[v];
        mx[u]=max(mx[u],siz[v]);
    }
    mx[u]=max(mx[u],S-mx[u]);
    if(mx[u]<mx[root]) root=u;

}

void calc(int u,int fa)
{
    siz[u]=1;bit[u]<<=w[u];
    for(int i=0,len=g[u].size();i<len;++i)
    {
        int v=g[u][i];
        if(vis[v]||v==fa) continue;
        bit[v]=bit[u];
        calc(v,u);
        bit[u]|=bit[v];
        siz[u]+=siz[v];
    }
}

void solve(int u)
{
    vis[u]=true;
    bit[u].reset();bit[u].set(0);
    calc(u,0);
    ans|=bit[u];
    for(int i=0,len=g[u].size();i<len;++i)
    {
        int v=g[u][i];
        if(vis[v]) continue;
        root=0; S=siz[v];
        getroot(v,0);
        solve(root);
    }

}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        ans.reset();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) g[i].clear(),vis[i]=0;
        for(int i=1;i<n;++i)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for(int i=1;i<=n;++i) scanf("%d",w+i);
        S=n; root=0;mx[0]=INF;
        getroot(1,0);
        solve(1);
        for(int i=1;i<=m;++i)
            printf("%d",(int)ans[i]);
        puts("");

    }

    return 0;
}

Problem J. Master of GCD

题意:

  给出T组数据(1 <= T  <= 10),每组数据中,有两个数n(1  <= n <= 10^5)和 m (1 <= m <= 10^5)。其中 n 表示有n个由1组成的数, m表示下面给出m组数据,每组数据由 p,q,k 组成。表示区间p 到 q,增大k倍(k 等于2 或者 3).输出这n个数最终的最大公约数。由于数据比较大,因此需要mod 998244353。 
  差分一下,维护2的次幂和3的次幂;

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 998244353
typedef long long ll;
const int maxn=1e5+10;
int T,n,m;
ll x[maxn],y[maxn];
ll qpow(ll x,ll y)
{
    ll res=1;
    while(y)
    {
        if(y&1) res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;++i) x[i]=y[i]=0;
        for(int i=1;i<=m;++i)
        {
            int l,r,xx;
            scanf("%d%d%d",&l,&r,&xx);
            if(xx==2) x[l]++,x[r+1]--;
            else y[l]++,y[r+1]--;
        }

        for(int i=2;i<=n;++i) x[i]+=x[i-1],y[i]+=y[i-1];
        ll ans1=x[1],ans2=y[1];
        for(int i=2;i<=n;++i)
            ans1=min(ans1,x[i]),ans2=min(ans2,y[i]);
        ll ans=qpow(2,ans1)*qpow(3,ans2)%mod;
        printf("%lld\n",ans);
    }

    return 0;
}

Problem K. Master of Sequence

题解:

参考代码:

#include<bits/stdc++.h>
#define mod 998244353
const int maxn=1e6+10;
using namespace std;
typedef long long ll;
struct node{
    ll a,b;
} p[maxn];
int T,n,m,num[1010][1010],cnt[1010];
ll s;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        s=0;
        memset(num,0,sizeof num);
        memset(cnt,0,sizeof cnt);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&p[i].a);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&p[i].b);
            s+=(p[i].b/p[i].a);
            cnt[p[i].a]++;
            num[p[i].a][p[i].b%p[i].a]++;
        }
        for(int i=1;i<=1000;i++)
            for(int j=i-1;j>=0;j--)
                num[i][j]+=num[i][j+1];

        while(m--)
        {
            int ty,y,z;
            scanf("%d",&ty);
            if(ty==1)
            {
                scanf("%d%d",&y,&z);
                for(int i=p[y].b%p[y].a;i>=1;--i) num[p[y].a][i]--;
                s-=(p[y].b/p[y].a);
                cnt[p[y].a]--;
                p[y].a=z;
                s+=(p[y].b/p[y].a);
                cnt[z]++;
                for(int i=p[y].b%z;i>=1;--i) num[z][i]++;
            }
            else if(ty==2)
            {
                scanf("%d%d",&y,&z);
                for(int i=p[y].b%p[y].a;i>=1;--i) num[p[y].a][i]--;
                s-=(p[y].b/p[y].a);
                p[y].b=z;
                s+=(p[y].b/p[y].a);
                for(int i=p[y].b%p[y].a;i>=1;--i) num[p[y].a][i]++;
            }
            else
            {
                ll k;
                scanf("%lld",&k);
                ll l=1,r=1e13,ans;
                while(l<=r)
                {
                    ll mid=l+r>>1;
                    ll sum=-s;
                    for(int i=1;i<=1000;++i) sum+=mid/i*cnt[i]-num[i][mid%i+1];
                    if(sum>=k) r=mid-1,ans=mid;
                    else l=mid+1;
                }
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}



 

原文地址:https://www.cnblogs.com/songorz/p/11764086.html

时间: 2024-08-29 15:29:23

2017 CCPC杭州 题解的相关文章

2017 CCPC 杭州赛区小结 By JSB @ Reconquista

Statistics TYPE: Onsite Contest NAME: 2017 - CCPC - Hangzhou PLAT: pc^2 TIME: 2017/11/05 09:00-14:00 LOCA: Zhejiang SCI-TECH University Xiasha Campus TEAM: Reconquista[shb,lsmll,jsb] RANK: 10/190 5.26% (*Including Unofficial Teams) SOLVE: 7/12 PENALT

HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)

题目链接  2017 CCPC Hangzhou Problem H 思路:对树进行分块.把第一棵树分成$\sqrt{n}$块,第二棵树也分成$\sqrt{n}$块.    分块的时候满足每个块是一个连通块,那么每个块就有一个共同的祖先. 把询问按照第一个点被第一棵树的哪个祖先管辖和第二个点被第二棵树的哪个祖先管辖,分成$n$类. 每一类询问一起处理,处理完后用可撤销并查集恢复到之前的状态. 每一类询问之间依次转移,每次转移,移动次数不会超过$\sqrt{n}$次. 最后总时间复杂度$O(n^{

2017 CCPC 杭州

Time: Link A 题意 分析 B 题意 分析 C 题意 分析 D 题意 分析 E 题意 分析 F 题意 分析 G 题意 分析 H 题意 分析 I 题意 分析 J 题意 分析 K 题意 分析 Summary: Ym:铁牌++ Czh: 原文地址:https://www.cnblogs.com/Deadline/p/9601892.html

2017 CCPC Final小结 By JSB @ Reconquista

Statistics TYPE: Onsite Contest NAME: 2017 - CCPC - Final PLAT: pc^2 TIME: 2017/12/03 09:00-14:00 LOCA: Harbin Institute of Technology TEAM: Reconquista [shb,lsmll,jsb] RANK: 3/117 2.56% (*Including Unofficial Teams) SOLVE: 9/11 PENALTY: 884 ? A - 11

HDU 6240 Server(2017 CCPC哈尔滨站 K题,01分数规划 + 树状数组优化DP)

题目链接  2017 CCPC Harbin Problem K 题意  给定若干物品,每个物品可以覆盖一个区间.现在要覆盖区间$[1, t]$. 求选出来的物品的$\frac{∑a_{i}}{∑b_{i}}$的最小值. 首先二分答案,那么每个物品的权值就变成了$x * b_{i} - a_{i}$ 在判断的时候先把那些权值为正的物品全部选出来, 然后记录一下从$1$开始可以覆盖到的最右端点的位置. 接下来开始DP,按照区间的端点升序排序(左端点第一关键字,右端点第二关键字) 问题转化为能否用剩

CCPC杭州赛总结

相比于之前的比赛,这次比赛我没有任何包袱,轻装上阵,热身赛前两天晚上八点坐公交车去火车站,路上堵车,差点错过火车,还好一切顺利到了杭州预定的宾馆,这已经是热身赛前一天的下午四点钟了,相当于20个小时的车程,晚上和河南学校的一群大佬在一起聊天(虽然我并没有说很多话).    睡一觉醒来已经是热身赛那天的上午,和队友zjd&&zgp还有在杭州工作的学姐wh一起去杭电报道领取参赛服以及参赛手册等物品,接着就在杭电吃了午饭,又在杭电转了一圈,闲暇之余看到了狗狗和鸭子在湖中长达十分钟之久的追逐大战,

河南工业大学2017校赛题解

问题 A: 饶学妹的比赛 题意: 给你一场比赛每人提交的记录,计算最后的排名 题解: 模拟+排序 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #

2017寒假练习题解 第四周 2.6-2.12

2.6 Problem A Quasi Binary 题意:给出 n ,输出n至少由k个只含 01的数组成 简析:按照 n 的位数如果相应的一位不是0的话,就填 1 ,再减去,直到减到 n 为0 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8

2017 ccpc女生专场 1003 Coprime Sequence

前缀后缀gcd,其实自己中用的是种奇怪的方法A掉的,不过先把这个学上,自己的方法有时间再填. 题意 告诉你N个数,求删除一个数可以求得最大GCD. N可能是100000. 思路 这道题其实很简单,但是想不到这点就很难. 简单的说就是先预处理,得到每个数字左边的GCD和右边的GCD. befor(i)代表前i个数字的GCD, 复杂度 O(n*log(n)) after(i)代表i之后的数字的GCD. 复杂度 O(n*log(n)) ans = max(after(2), befor(1)+afte