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;
}