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\)啦!

  • \(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;
}
posted @ 2019-10-14 17:33  源曲明  阅读(237)  评论(0编辑  收藏  举报