2017ccpc杭州站题解

A 贪心,找奇偶数分别最大

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int a[30];
int b[30];
int main(){
    ios::sync_with_stdio(false);
    int i;
    int t;
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        int cnt=(int)s.size();
        s=" "+s;
        for(i=1;i<(int)s.size();i++){
            int sign=s[i]-'a';
            if(i%2){
                a[sign]++;
            }
            else{
                b[sign]++;
            }
        }
        int mx1=0,mx2=0;
        for(i=0;i<26;i++){
            mx1=max(mx1,a[i]);
            mx2=max(mx2,b[i]);
        }
        cout<<cnt-mx1-mx2<<endl;
    }
    return 0;
}
View Code

B模拟

#include<cstdio>
#define LL long long
using namespace std;
const int mod=998244353;

LL qpow(LL m,LL k)
{
    LL res=1%mod;
    LL t=m%mod;
    while(k)
    {
        if(k&1)
            res=res*t%mod;
        t=t*t%mod;
        k>>=1;
    }
    return res%mod;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        LL ans=1;
        for(int i=1;i<=n;i++)
        {
            LL p,q;
            scanf("%lld%lld",&p,&q);
            LL tmp=((qpow(p,q-1)*(p-1))%mod*q)%mod;
            ans=(ans*(qpow(p,q)+tmp)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

C博弈,与%3相同

#include<cstdio>
using namespace std;
int a[1000005];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,d;
        scanf("%d%d",&n,&d);
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==1)
                sum++;
        }
        if(d==1)
        {
            if(n%3==0&&sum==n)
                printf("No\n");
            else
                printf("Yes\n");
        }
        else
        {
            if(n%3==1&&sum>=n-1)
                printf("No\n");
            else if(n%3==0&&sum==n-1)
                printf("No\n");
            else
                printf("Yes\n");
        }
    }
    return 0;
}
View Code

D找规律

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
const ll mod=998244353;
ll a[N];
ll f[N];
ll fac[123456];
ll qmi(ll a,ll b){
    a%=mod;
    ll res=1;
    while(b){
        if(b&1){
            res=res*a%mod;
        }
        b>>=1;
        a=a*a%mod;
    }
    return res;
}
int main(){
    fac[0]=1;
    for(ll i=1;i<=100005;i++)
        fac[i]=fac[i-1]*i%mod;
    f[1]=2;
    f[0]=1;
    ll g=1;
    for(int i=2;i<=100005;i++){
        f[i]=(2*f[i-1]%mod+g)%mod;
        g=g*2%mod;
    }
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int i;
        for(i=0;i<=n-1;i++){
            cin>>a[i];
        }
        ll tmp=fac[n-1]*a[0]%mod;
        ll t=fac[n-1];
        for(i=1;i<=n-1;i++){
            t=t+fac[n-1]*qmi(i,mod-2)%mod;
            t%=mod;
            tmp=(tmp+a[i]*t)%mod;
        }
        ll sum=fac[n];
        cout<<tmp*qmi(sum,mod-2)%mod<<endl;
    }
    return 0;
}
View Code

E点分治+bitset(观察数据范围只有3000可猜测)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
const int mod=1e7+7;
int n,idx;
int h[N],ne[N],e[N],w[N];
int cnt[N],vis[N],d[N],sz[N];
int dis[N];
int st[N];
int root;
int m;
bitset<100010> bit[3030],ans;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs_root(int u,int fa,int tot){
    int i;
    sz[u]=1;
    int ans=0;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa||vis[j])
            continue;
        dfs_root(j,u,tot);
        sz[u]+=sz[j];
        ans=max(ans,sz[j]);
    }
    ans=max(ans,tot-sz[u]);
    if(ans*2<=tot){
        root=u;
    }
}
void dfs_sz(int u,int fa){
    sz[u]=1;
    int i;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa||vis[j])
            continue;
        dfs_sz(j,u);
        sz[u]+=sz[j];
    }
}
void get(int u,int fa){
    bit[u]<<=w[u];
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa||vis[j])
            continue;
        bit[j]=bit[u];
        get(j,u);
        bit[u]|=bit[j];
    }
}
void work(int u,int tot){
    dfs_root(u,-1,tot);
    u=root;
    vis[u]=1;
    dfs_sz(u,-1);
    bit[u].reset();
    bit[u].set(0);
    get(u,-1);
    ans|=bit[u];
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(vis[j])
            continue;
        work(j,sz[j]);
    }
}
int main(){
    //ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        int n;
        scanf("%d%d",&n,&m);
        int i;
        ans.reset();
        idx=0;
        for(i=0;i<=n;i++){
             h[i]=-1;
             vis[i]=0;
        }
        for(i=1;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(i=1;i<=n;i++)
            scanf("%d",&w[i]);
        work(1,n);
        for(i=1;i<=m;i++){
            printf("%d",(int)ans[i]);
        }
        printf("\n");
    }
    return 0;
}
View Code

 

J 差分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>

using namespace std;
typedef long long ll;
ll mod=998244353;
int a[100005];
int b[100005];
ll ksm(ll x,ll y){
ll res=1;
    while(y){
        if(y&1)res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res%mod;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        while(m--){
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            if(x==2){
                a[l]++;a[r+1]--;
            }
            else{
                b[l]++;b[r+1]--;
            }
        }
        int sa,sb;
        sa=sb=10000000;

        for(int i=1;i<=n;i++){
            a[i]=a[i-1]+a[i];
            b[i]=b[i-1]+b[i];
            sa=min(sa,a[i]);
            sb=min(sb,b[i]);
        }
        ll res=1;
        res=ksm(2,sa)%mod*ksm(3,sb)%mod;
        cout<<res<<endl;
    }
}
View Code

K 二分+预处理

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll inf=1e15;
typedef long long ll;
int n,m;
ll sum[2020][2020];
int a[N],b[N];
ll ans=0;
bool check(ll x,ll y){
    ll res=0;
    for(int i=1;i<=1000;i++){
        res+=sum[i][0]*(x/i);
        res-=sum[i][x%i+1];
    }
    return res>=y;
}
ll solve(ll x){
    ll l=1,r=inf;
    while(l<r){
        ll mid=l+r>>1;
        if(check(mid,x)){
            r=mid;
        }
        else{
            l=mid+1;
        }
    }
    return l;
}
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m;
        int i,j;
        ans=0;
        for(i=1;i<=1000;i++){
            for(j=0;j<=1000;j++)
                sum[i][j]=0;
        }
        for(i=1;i<=n;i++){
            cin>>a[i];
        }
        for(i=1;i<=n;i++){
            cin>>b[i];
        }
        for(i=1;i<=n;i++){
            sum[a[i]][b[i]%a[i]]++;
            ans+=b[i]/a[i];
        }
        for(i=1;i<=1000;i++){
            for(j=i-1;j>=0;j--){
                sum[i][j]+=sum[i][j+1];
            }
        }
        while(m--){
            int opt;
            cin>>opt;
            ll x,y;
            if(opt==1){
                cin>>x>>y;
                ans-=b[x]/a[x];
                ans+=b[x]/y;
                for(i=b[x]%a[x];i>=0;i--){
                    sum[a[x]][i]--;
                }
                for(i=b[x]%y;i>=0;i--){
                    sum[y][i]++;
                }
                a[x]=y;
            }
            else if(opt==2){
                cin>>x>>y;
                ans-=b[x]/a[x];
                ans+=y/a[x];
                for(i=b[x]%a[x];i>=0;i--){
                    sum[a[x]][i]--;
                }
                for(i=y%a[x];i>=0;i--){
                    sum[a[x]][i]++;
                }
                b[x]=y;
            }
            else{
                cin>>x;
                cout<<solve(x+ans)<<endl;
            }
        }
    }
}
View Code

L 类欧几里得

#include <bits/stdc++.h>
#define rint register int
#define inv inline void
#define ini inline int
#define maxn 1000050
using namespace std;
typedef long long ll;
typedef long long LL;
char s[maxn];
int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn],wt[30];
//rk代表i的排名,sa代表排名为i的后缀位置
int n,m;
inv putout(int x)
{
    if(!x) {putchar(48);return;}
    rint l=0;
    while(x) wt[++l]=x%10,x/=10;
    while(l) putchar(wt[l--]+48);
}
inv get_SA()
{
    for (rint i=1;i<=n;++i) ++c[x[i]=s[i]];//c数组是桶,x[i]是第i个元素的第一关键字
    for (rint i=2;i<=m;++i) c[i]+=c[i-1];//做c的前缀和,我们就可以得出每个关键字最多是在第几名
    for (rint i=n;i>=1;--i) sa[c[x[i]]--]=i;
    for (rint k=1;k<=n;k<<=1)
    {
        rint num=0;
        for (rint i=n-k+1;i<=n;++i) y[++num]=i;
        //y[i]表示第二关键字排名为i的数,第一关键字的位置
        //第n-k+1到第n位是没有第二关键字的 所以排名在最前面
        for (rint i=1;i<=n;++i) if (sa[i]>k) y[++num]=sa[i]-k;
        //排名为i的数 在数组中是否在第k位以后
        //如果满足(sa[i]>k) 那么它可以作为别人的第二关键字,就把它的第一关键字的位置添加进y就行了
        //所以i枚举的是第二关键字的排名,第二关键字靠前的先入队
        for (rint i=1;i<=m;++i) c[i]=0;//初始化c桶
        for (rint i=1;i<=n;++i) ++c[x[i]];//因为上一次循环已经算出了这次的第一关键字 所以直接加就行了
        for (rint i=2;i<=m;++i) c[i]+=c[i-1];//第一关键字排名为1~i的数有多少个
        for (rint i=n;i>=1;--i) sa[c[x[y[i]]]--]=y[i],y[i]=0;
        //因为y的顺序是按照第二关键字的顺序来排的
        //第二关键字靠后的,在同一个第一关键字桶中排名越靠后
        //基数排序
        swap(x,y);//这里不用想太多,因为要生成新的x时要用到旧的,就把旧的复制下来,没别的意思
        x[sa[1]]=1;num=1;
        for (rint i=2;i<=n;++i)
            x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) ? num : ++num;
        //因为sa[i]已经排好序了,所以可以按排名枚举,生成下一次的第一关键字
        if (num==n) break;
        m=num;
        //这里就不用那个122了,因为都有新的编号了
    }
    for (rint i=1;i<=n;++i) putout(sa[i]),putchar(' ');
}
inv get_height()
{
    rint k=0;
    for (rint i=1;i<=n;++i) rk[sa[i]]=i;
    for (rint i=1;i<=n;++i)
    {
        if (rk[i]==1) continue;//第一名height为0
        if (k) --k;//h[i]>=h[i-1]+1;
        rint j=sa[rk[i]-1];
        while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
        height[rk[i]]=k;//h[i]=height[rk[i]];
    }
    putchar(10);for (rint i=1;i<=n;++i) putout(height[i]),putchar(' ');
}
const ll mo=2;
LL f(LL a,LL b,LL c,LL n)
{
    if (!a) return (n+1)*(b/c)%mo;
    if (a>=c || b>=c)
    {
        LL sqr=(n&1) ?(n+1)/2*n :n/2*(n+1) ;
        return (f(a%c,b%c,c,n)+(a/c)*sqr+(n+1)*(b/c))%mo;
    } else
    {
        LL m=(a*n+b)/c;
        return (m*n-f(c,c-b-1,a,m-1)+mo)%mo;
    }
}
int main()
{
    //freopen("../in.in", "r", stdin);
//    freopen("../out.out","w",stdout);
    //ios::sync_with_stdio(false);
//    gets(s+1);
//    n=strlen(s+1);m=122;//n表示原字符串长度,m表示字符个数,ascll('z')=122
//    get_SA();
        int t;
        scanf("%d",&t);
        while(t--){
            ll n;
            scanf("%lld",&n);
            ll ans=0,sqrtn=min(30000000ll,n);
            for(ll i=1;i<=sqrtn;i++)
                ans^=n%i;
            for(ll l=sqrtn+1,r;l<=n;l=r+1){
                r=n/(n/l);
                ll ean=0;
                ll lim=n/l*(r-l)+n%r;
                for(ll c=1;c<=lim;c<<=1){
                    if(f(n/l,n%r,c,r-l))ean+=c;
                }
                ans^=ean;
            }
            printf("%lld\n",ans);
        }
    //get_height();
}
View Code

 

posted @ 2020-09-26 09:44  朝暮不思  阅读(231)  评论(0编辑  收藏  举报