Code Chef October Challenge 2019题解

传送门

\(MSV\)

设个阈值搞一搞就行了

//quming
#include<bits/stdc++.h>
#define R register
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=1e6+5,L=1e6,S=300;
int sz[N],cnt[N],x,n,T,res,ret;
int main(){
    for(scanf("%d",&T);T;--T){
        scanf("%d",&n),res=0;
        fp(i,1,n){
            scanf("%d",&x);
            if(x<=S)cmax(res,cnt[x]);
            else{
                ret=0;
                for(R int j=x;j<=L;j+=x)ret+=sz[j];
                cmax(res,ret);
            }
            ++sz[x];
            fp(j,1,min(S,x))if(x%j==0)++cnt[j];
        }
        fp(i,1,L)sz[i]=0;
        fp(i,1,S)cnt[i]=0;
        printf("%d\n",res);
    }
    return 0;
}

\(B\)

根据总的次数搞一搞就行了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=10005;
ll k,c;int a[N],n,T;
inline void sl1(){
    fp(i,0,(n-2)>>1){
        R int x=a[i],y=a[n-1-i],z=x^y;
        a[i]=z,a[n-1-i]=x;
    }
}
inline void sl2(){
    fp(i,0,(n-2)>>1){
        R int x=a[i],y=a[n-1-i],z=x^y;
        a[i]=y,a[n-1-i]=z;
    }
}
int main(){
    for(scanf("%d",&T);T;--T){
        scanf("%d%lld",&n,&k);
        fp(i,0,n-1)scanf("%d",&a[i]);
        c=k/n,k%=n;
        switch(c%3){
            case 1:sl1();break;
            case 2:sl2();break;
        }
        if(n&1)a[n>>1]=(c?0:a[n>>1]);
        fp(i,0,k-1)a[i]=a[i]^a[n-1-i];
        fp(i,0,n-1)printf("%d ",a[i]);
        puts("");
    } 
    return 0;
}

\(EVEDG\)

如果\(m\)是偶数全都扔一个集合里

否则如果有一个点的度数是奇数,那么把这个点单独一个集合,其它的放一起

如果没有点的度数是奇数,那么随便找一条边,把这条边连的两个点设成不同的颜色,其他所有点为第三个颜色

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=1e5+5;
int deg[N],n,m,T,u,v,s;
int main(){
    for(scanf("%d",&T);T;--T){
        scanf("%d%d",&n,&m);
        memset(deg,0,(n+1)<<2);
        fp(i,1,m)scanf("%d%d",&u,&v),deg[u]^=1,deg[v]^=1;
        if(m&1^1){
            puts("1");
            fp(i,1,n)printf("%d ",1);
            puts("");
            continue;
        }
        s=0;fp(i,1,n)if(deg[i]&1){s=i;break;}
        if(s){
            puts("2");
            fp(i,1,s-1)printf("%d ",1);
            printf("%d ",2);
            fp(i,s+1,n)printf("%d ",1);
            puts("");
            continue;
        }
        if(u>v)swap(u,v);
        puts("3");
        fp(i,1,u-1)printf("%d ",1);
        printf("%d ",2);
        fp(i,u+1,v-1)printf("%d ",1);
        printf("%d ",3);
        fp(i,v+1,n)printf("%d ",1);
        puts("");
        continue;
    }
    return 0;
}

\(BACREP\)

不考虑子树问题的话一个修改可以看成在\(t-dep[u]\)的位置放了\(k\)个,然后询问可以看成在\(t-dep[u]\)的位置有多少个,叶子的话就是做个前缀和

考虑子树问题的话我们离线,按\(dfs\)序遍历一遍,进子树时修改,出子树时撤销修改就行了

//quming
#include<bits/stdc++.h>
#define R register
#define fi first
#define se second
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
inline char getop(){R char ch;while((ch=getc())!='+'&&ch!='?');return ch;}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R ll x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e6+55,M=5e5+10;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
ll c[N];int n,q;
inline void chg(R int x,R int y){for(x+=M;x<=q+M;x+=x&-x)c[x]+=y;}
inline ll query(R int x){R ll res=0;for(x+=M;x;x-=x&-x)res+=c[x];return res;}
vector<pi>ch[N];vector<int>qr[N];
ll ans[N];int vq[N],sz[N],dep[N],a[N],cnt;
void dfs(int u,int fa){
    dep[u]=dep[fa]+1,sz[u]=0;
    go(u)if(v!=fa)++sz[u],dfs(v,u);
}
void find(int u,int fa){
    for(auto v:ch[u])chg(v.fi-dep[u],v.se);
    for(auto v:qr[u])ans[v]=query(v-dep[u]);
    if(sz[u])for(auto v:qr[u])ans[v]-=query(v-dep[u]-1);
    go(u)if(v!=fa)find(v,u);
    for(auto v:ch[u])chg(v.fi-dep[u],-v.se);
}
int main(){
//  freopen("testdata.in","r",stdin);
    n=read(),q=read();
    for(R int i=1,u,v;i<n;++i)u=read(),v=read(),add(u,v),add(v,u);
    fp(i,1,n)a[i]=read();
    dfs(1,0);
    fp(i,1,n)ch[i].pb(pi(0,a[i]));
    for(R int i=1,u,x,op;i<=q;++i){
        op=getop(),u=read();
        if(op=='+')x=read(),ch[u].pb(pi(i,x));
            else qr[u].pb(i),vq[i]=1;
    }
    find(1,0);
    fp(i,1,q)if(vq[i])print(ans[i]);
    return Ot(),0;
}

\(TANDON\)

有种在做提答题的感觉……

首先鉴于某些边界原因如果\(n\leq 6\)我们直接跑暴力

然后我们接下来就直接枚举\(k\)啦!

扫描二维码关注公众号,回复: 7464753 查看本文章
  • \(k=10\),只有\(0\)合法

  • \(k=2\),最高位为\(2,4,6,8\),最低位为\(0,2,4,6,8\),中间可以随便选,那么枚举总位数然后等比数列求和即可,记得最后加上总位数小于\(2\)的情况

  • \(k=4\),一个数为\(4\)的倍数当且仅当后两位是\(4\)的倍数,那么打个表看一下可以做后两位的数的个数和前两位的数的个数,中间随便选,记得最后加上总位数小于\(4\)的情况

  • \(k=8\),一个数为\(8\)的倍数当且仅当后三位是\(8\)的倍数,其他同上

  • \(k=5\),最高位是\(5\),最低位是\(0,5\),中间随便选,其余同\(k=2\)

  • \(k=3\),发现\(3\)的倍数反转依然是\(3\)的倍数,那么答案就是\(0\)\(10^n-1\)\(3\)的倍数的个数

  • \(k=9\),同\(k=3\)

  • \(k=6\),首先要满足\(k=2\)的情况,其次要满足所有位加起来是\(3\)的倍数,那么假设现在中间的位数为\(i\),记\(p={10^i-1\over 3}\),则有中间那几位\(p\)种选法使和模\(3\)\(1\)\(2\),有\(p+1\)种选法使和模\(3\)\(0\),再根据选择的首位末位加起来模\(3\)的余数讨论一下就行了

  • \(k=7\),这个东西啥性质都没有,只能爆算了,设\(f[i][j][k]\)表示考虑到第\(i\)位,且原数模\(7\)余数为\(j\),翻转之后模\(7\)\(k\)的方案数,那么\(f[n][0][0]\)就是答案了

暴力的代码如下

int calc(){
    memset(f,0,sizeof(f));
    f[0][0][0]=1,t=0,p=1;
    fp(i,0,n-1){
        memset(f[t^1],0,sizeof(f[t^1]));
        fp(j,0,6)fp(k,0,6)if(f[t][j][k])
            fp(l,0,9)upd(f[t^1][(j+l*p)%7][(k*10+l)%7],f[t][j][k]);
        p=p*10%7,t^=1;
    }
    return f[t][0][0];
}

事实上这个也可以扩展到\(k\)为其它的情况,不过仔细思考之后你可以惊喜的发现除了\(k=3,7,9\)之外其它全都是错的

既然已经写出暴力了用矩乘优化一下就行了

//quming
#include<bits/stdc++.h>
#define R register
#define gg(x) printf("%d\n",x);break;
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7,inv3=333333336;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    return res;
}
int kkk(R int x,R int y){
    //求1+x+x^2+...+x^y 
    R int res=1,d=1;
    for(;y;y>>=1,d=mul(d,x+1),x=mul(x,x))(y&1)?res=add(mul(res,x),d):0;
    return res;
}
inline int rev(R int x){R int res=0;while(x)res=res*10+x%10,x/=10;return res;}
int r[1000005];
const int N=55;
struct Matrix{
    int a[N][N];
    inline Matrix(){memset(a,0,sizeof(a));}
    inline int* operator [](const int &x){return a[x];}
    inline Matrix operator *(Matrix b){
        Matrix c;
        fp(i,1,49)fp(k,1,49)fp(j,1,49)upd(c[i][j],mul(a[i][k],b[k][j]));
        return c;
    }
}mi[15],bin[35];
int id[15][15];
void init(){
    R int p=1,tot=0;
    fp(i,0,6)fp(j,0,6)id[i][j]=++tot;
    fp(i,1,6){
        fp(j,0,6)fp(k,0,6)fp(l,0,9)++mi[i][id[j][k]][id[(j+l*p)%7][(k*10+l)%7]];
        p=p*10%7;
    }
    fp(i,1,49)bin[0][i][i]=mi[0][i][i]=1;
    fp(i,2,6)mi[i]=mi[i-1]*mi[i];
    bin[1]=mi[6];
    fp(i,2,30)bin[i]=bin[i-1]*bin[i-1];
}
int f[2][N][N],bas,t,p,T,n;
Matrix ksm(R int y){
    Matrix res=bin[0];
    for(R int i=1;y;y>>=1,++i)if(y&1)res=res*bin[i];
    return res;
}
int calc(){
    Matrix ret;ret[1][1]=1;
    ret=ret*ksm(n/6),ret=ret*mi[n%6];
    return ret[1][1];
}
inline int brute(){
    R int res=1,p=ksm(10,n);
    for(R int i=bas;i<p;i+=bas)if(r[i]%bas==0)++res;
    return res;
}
int main(){
//  freopen("testdata.in","r",stdin);
    fp(i,1,1e6)r[i]=rev(i);
    init();
    for(scanf("%d",&T);T;--T){
        scanf("%d%d",&n,&bas);
        if(n<=6){printf("%d\n",brute());continue;}
        switch(bas){
            case 10:gg(1);
            case 2:gg(add(mul(20,kkk(10,n-2)),5));
            case 5:gg(add(mul(2,kkk(10,n-2)),2));
            case 4:gg(add(mul(500,kkk(10,n-4)),59));
            case 8:gg(add(mul(12500,kkk(10,n-6)),1392));
            case 3:gg(mul(3,kkk(10,n-1))+1);
            case 9:gg(kkk(10,n-1)+1);
            case 6:{
                R int p=kkk(10,n-2);
                R int res=add(mul(14,dec(p,n-1)),mul(6,add(p,mul(2,n-1))));
                printf("%d\n",mul(res,inv3)+2);
                break;
            }
            case 7:gg(calc());
        }
    }
    return 0;
}

\(JIIT\)

生成函数差的一比……所以还是看\(jz\)姐姐说的吧

然后我就卡了一个晚上的常……\(zyy\)聚聚似乎随便过,不知道他写了个什么……

//quming
#include<bits/stdc++.h>
#define R register
#define fi first
#define se second
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef vector<int> poly;
typedef long long ll;
const int P=998244353,inv2=499122177;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R ll y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    return res;
}
const int N=5005;
poly e,eg,ef,bf[N],bg[N];int bin[N],ibin[N],fac[N],ifac[N],n,m,T,z,res;
ll q;int np[N],sr[N],sc[N];
poly operator *(const poly &a,const poly &b){
    int n=a.size(),m=b.size(),dn=n-1,dm=m-1,dc=dn+dm;
    poly c(dc+1);
    fp(i,0,n-1)fp(j,0,m-1)upd(c[i+j],mul(a[i],b[j]));
    return c;
}
poly Dg(const poly &a){
    int n=a.size(),dn=n-1,dc=dn-1,t;
    poly c(dc+1),d(a);
    for(R int i=dn,j=dc;i;--i,--j){
        t=c[j]=d[i];
        d[i]=dec(d[i],t),d[i-1]=dec(d[i-1],t);
    }
    return c;
}
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
void init(){ 
    /*
        多项式第i项的系数表示e^{ix}的系数 
        又因为所有形如e^x+e^{-x}的幂次的形式里只有一半的系数不为0
        所以多项式里只考虑那些系数不为0的项了 
    */
    e.resize(1),e[0]=1;
    ef.resize(2),ef[0]=P-1,ef[1]=1;
    eg.resize(2),eg[0]=1,eg[1]=1;
    bf[0]=bg[0]=e;
    fp(i,1,2000)bf[i]=bf[i-1]*ef;
    fp(i,1,2000)bg[i]=bg[i-1]*eg;
    fac[0]=ifac[0]=1;fp(i,1,2000)fac[i]=mul(fac[i-1],i);
    ifac[2000]=ksm(fac[2000],P-2);fd(i,2000-1,1)ifac[i]=mul(ifac[i+1],i+1);
    bin[0]=ibin[0]=1;
    fp(i,1,2000)bin[i]=mul(bin[i-1],2),ibin[i]=mul(ibin[i-1],inv2);
}
inline int calc(const poly &A,R int p){
    R int ret=0;
    for(R int i=0,j=-p;j<0;++i,j+=2)upd(ret,mul(A[i],q&1?P-np[-j]:np[-j]));
    for(R int i=p,j=p;j>0;--i,j-=2)upd(ret,mul(A[i],np[j]));
    return ret;
}
void calc(int n,int *s){
    poly c=bg[n];
    fp(i,0,n)c[i]=mul(c[i],ibin[n]);
    s[0]=calc(c,n);
    fp(i,1,n)c=Dg(c),c=c*ef,s[i]=mul(C(n,i),calc(c,n)); 
}
int main(){
//  freopen("testdata.in","r",stdin);
    init();
    for(scanf("%d",&T);T;--T){
        scanf("%d%d%lld%d",&n,&m,&q,&z),res=0;
        np[0]=1;fp(i,1,max(n,m))np[i]=ksm(i,q);
        calc(n,sc),calc(m,sr);
        fp(i,0,n)fp(j,0,m)if(i*(m-j)+j*(n-i)==z)
            upd(res,mul(sc[i],sr[j]));
        printf("%d\n",res);
    }
    return 0;
}

\(CNNCT2\)

裸的拟阵交,具体可以看18年论文《浅谈拟阵的一些拓展及其应用 杨乾澜》

//quming
#include<bits/stdc++.h>
#define R register
#pragma GCC optimize(3)
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=305,M=N*N;
struct eg{int v,nx;}e[M];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
struct EG{int u,v;}f[N],g[N];
int fa[N],ga[N],st[N],vis[N],va[N],vb[N],vc[N],fr[N],ok[N],q[N];
int n,m,T,top;
inline int find(R int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline int gind(R int x){return ga[x]==x?x:ga[x]=gind(ga[x]);}
bool bfs(){
    R int h=1,t=0,u;
    fp(i,1,m){
        ok[i]=vc[i]=fr[i]=0;
        if(va[i])q[++t]=i,ok[i]=1;
    }
    while(h<=t){
        u=q[h++];if(vb[u])break;
        go(u)if(!ok[v])q[++t]=v,fr[v]=u,ok[v]=1;
    }
    if(!vb[u])return false;
    for(;u;u=fr[u])vc[u]=1;
    return true;
}
void solve(){
    top=0;
    fp(i,1,m)vis[i]=0;
    while(true){
        memset(head,0,(m+1)<<2),tot=0;
        fp(k,1,top){
            fp(i,1,n)fa[i]=ga[i]=i;
            fp(i,1,top)if(i!=k){
                fa[find(f[st[i]].u)]=find(f[st[i]].v);
                ga[gind(g[st[i]].u)]=gind(g[st[i]].v);
            }
            fp(i,1,m)if(!vis[i]){
                if(find(f[i].u)!=find(f[i].v))add(st[k],i);
                if(gind(g[i].u)!=gind(g[i].v))add(i,st[k]);
            }
        }
        fp(i,1,m)va[i]=vb[i]=vc[i]=0;
        fp(i,1,n)fa[i]=ga[i]=i;
        fp(i,1,top){
            fa[find(f[st[i]].u)]=find(f[st[i]].v);
            ga[gind(g[st[i]].u)]=gind(g[st[i]].v);
        }
        fp(i,1,m)if(!vis[i]){
            if(find(f[i].u)!=find(f[i].v))va[i]=1;
            if(gind(g[i].u)!=gind(g[i].v))vb[i]=1;
        }
        if(!bfs())break;
        top=0;
        fp(i,1,m)if(vis[i]^vc[i])st[++top]=i;
        fp(i,1,m)vis[i]=0;fp(i,1,top)vis[st[i]]=1;
    }
    printf("%d\n",((n-1)<<1)-top);
}
int main(){
//  freopen("testdata.in","r",stdin);
    for(scanf("%d",&T);T;--T){
        scanf("%d%d",&n,&m);
        fp(i,1,m)scanf("%d%d",&f[i].u,&f[i].v);
        fp(i,1,m)scanf("%d%d",&g[i].u,&g[i].v);
        solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yuanquming/p/11622925.html