这位巨佬的博客还是比我好多了
T1 工业题
考场:
暴力挺香的,不想正解了。
题解:
$f(i,j)$ 只会得到 $f(i-1,j)$ 和 $f(i,j-1)$ 的贡献。每向右一步乘 $a$ ,向下一步乘 $b$ 。左侧竖点有$inom{n+m-1-i}{m-1}$种走法,上侧横店有$inom{n+m-1-i}{n-1}$种走法.
预处理阶乘和阶乘逆元以及 $a,b$ 的幂次方即可。
#include<bits/stdc++.h> using namespace std; const int N=11000000,mod=998244353; long long a,b,n,m,inc[N],jc[N],am[N],bm[N],fheng[N],fshu[N],ans; long long quick_pow(long long x,long long y) { long long res=1; while(y) { if(y&1) { res=res*x%mod; } y>>=1; x=x*x%mod; } return res; } long long C(int n,int m) { return jc[n]*inc[m]%mod*inc[n-m]%mod; } int main() { scanf("%lld%lld%lld%lld",&n,&m,&a,&b); a%=mod;b%=mod; am[0]=bm[0]=jc[0]=inc[0]=1; for(int i=1;i<=n+m;i++) { jc[i]=jc[i-1]*i%mod; am[i]=am[i-1]*a%mod; bm[i]=bm[i-1]*b%mod; } inc[n+m]=quick_pow(jc[n+m],mod-2); for(int i=n+m-1;i>=1;i--) { inc[i]=inc[i+1]*(i+1)%mod; } for(int i=1;i<=n;i++) { scanf("%lld",&fheng[i]);fheng[i]%=mod; } for(int i=1;i<=m;i++) { scanf("%lld",&fshu[i]);fshu[i]%=mod; } for(int i=1;i<=n;i++) { ans+=fheng[i]*C(n+m-1-i,m-1)%mod*am[m]%mod*bm[n-i]%mod; ans%=mod; } for(int i=1;i<=m;i++) { ans+=fshu[i]*C(n+m-1-i,n-1)%mod*am[m-i]%mod*bm[n]%mod; ans%=mod; } printf("%lld ",ans); return 0; }
T2 卡常题
考场:
灵光乍现,发现如果把y部点删去,只剩下每个y点所连的边,题目所给的图就变成了一棵基环树。
原因:x,y部点都只有 $n$ 个如果把y点变成 $n$ 条边,那么由于题目保证联通且无重边,$n-1$ 的边构成一棵树,剩下的一条边随机连接,构成环。
问题就转化成了,在一棵基环树上,选择一个点的代价为该点所连边的权值和,选择的点可以“看守”所连的边,求所有边被看守的最小代价。
题解:
考场上我按照轮流断掉环中的每一条边,每次跑 $O(n)$ 树形DP来做的,即使看到能被卡成 $O(n^2)$ 的环形数据,依然执迷不悟。
事实上断哪一条边对答案完全没有影响,因为DP所求的和所需的完全没有变。 而且如果随机选一个点作为树根,难以保证断掉的边两侧的点一定选择了之一。
所以钦定其中一个点为根,跑两次DP。
#include<bits/stdc++.h> using namespace std; const int N=1100000,M=N<<1; int n,aa,bb,cnt=1,head[N],circle[N<<1],num,c1,c2,du[N],e,f[2][N][2],ans=0x7fffffff,sam[N]; bool vis[N],used[N]; inline int read() { int s=0,w=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} return s*w; } inline int _min(int a,int b) { return a<b?a:b; } struct bian { int nxt,to,w[2]; }b[M]; void add(int from,int to,bool g) { du[from]++;du[to]++; b[++cnt].w[g]=aa; b[cnt].w[g^1]=bb; b[cnt].nxt=head[from]; b[cnt].to=to; head[from]=cnt; } void findcir1(int u,int fa) { vis[u]=1; for(int i=head[u],v;i;i=b[i].nxt) { v=b[i].to; if(v==fa) continue; else if(vis[v]) { c1=u,c2=v;e=i; return; } else { findcir1(v,u); } } } bool findcir2(int u) { bool ok=0; for(int i=head[u],v;i;i=b[i].nxt) { if(used[i]) continue; v=b[i].to; circle[++num]=i; circle[++num]=i^1; used[i]=used[i^1]=1; if(du[v]==2) { circle[num--]=0; circle[num--]=0; continue; } if(v==c1) { ok=1;return ok; } ok=findcir2(v); if(!ok) { circle[num--]=0; circle[num--]=0; continue; } else return ok; } return ok; } void DP(int x,int fa,int o) { int sum=0; f[o][x][0]=0; f[o][x][1]=sam[x]; for(int i=head[x];i;i=b[i].nxt) { if(i==e||(i^1)==e||b[i].to==fa)continue; DP(b[i].to,x,o); sum+=min(f[o][b[i].to][0],f[o][b[i].to][1]); f[o][x][0]+=f[o][b[i].to][1]; } f[o][x][1]+=sum; } int main() { n=read();aa=read();bb=read(); for(int i=1,u,v;i<=n;i++) { u=read();v=read(); add(u,v,0); add(v,u,1); sam[u]+=aa; sam[v]+=bb; } findcir1(1,0); findcir2(c1); memset(used,0,sizeof(used)); DP(c1,0,0); DP(c2,0,1); printf("%d ",_min(f[0][c1][1],f[1][c2][1])); return 0; }
T3 玄学题
$egin{align}ans=sum_{i=1}^{n}(-1)^{sum_{j=1}^{m}d(i*j)}\ans=sum_{i=1}^{n}(-1)^{sum_{j=1}^{m}d(i*j) mod 2}end{align}$
因为奇+奇=偶,奇+偶=偶,偶+偶=偶,
所以,只有 $d(i*j)$ 为奇数,才对和式整体有贡献。
这时 $i*j$ 为完全平方数,假设i=p*q*q,那么 $j$ 是 $p*r*r$。
对于每一个 $i$,有$sqrt{lfloor frac{m}{p} floor}$ 个j对和式产生了贡献。
(只有能使 $-1$ 的幂增减 $1$ 的才算对和式产生了贡献)
#include<bits/stdc++.h> using namespace std; inline long long read() { long long s=0,w=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} return s*w; } const int N=11000000; long long n,m,ans,p[N]; bool flag[N]; int main() { n=read();m=read(); scanf("%lld%lld",&n,&m); for(int i=1;i*i<=n;i++) { for(int j=1;j*i*i<=n;j++) { p[i*i*j]=j; } flag[i*i]=1; } int s=sqrt(m); for(int i=1;i<=n;i++) { if(flag[i]) { if(s&1) ans--; else ans++; } else { int x=sqrt(m/p[i]); if(x&1) ans--; else ans++; } } printf("%lld ",ans) ; return 0; }
这两场都好拉跨啊QWQ每一次就离正解一步之遥。