标签:cdn map can 差分 class 固定 put sum 分析
分析:
考虑固定左端点L,枚举它
剩下的任务就是找到最小的R,使之[L,R]能够出现B的子序列
这样n-R+1也就满足,ans累加
代码是反着来的,效果是一样的
学到了
code by std
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long ans,f[105];
char s[100005],c[105];
int main(){
scanf("%d%d%s%s",&n,&m,s+1,c+1);
for(int i=1;i<=n;++i){
for(int j=m;j;--j){
if(s[i]!=c[j]) continue;
if(j==1) f[1]=i;
else f[j]=f[j-1];
}
ans+=f[m];
}
printf("%lld",ans);
return 0;
}
分析:
博弈论先考虑终止状态:(切记不要死循环的想)
先手只剩一条边时,先手必败
后手只剩两条边时,先手必胜
然后发现本题唯一和博弈论沾边的就是度数的奇偶性了(关键是找对立面)
1是奇数,扩展开去就是,先手面临奇数的时候一定是必败的
为什么?因为奇数删了一条边会变成偶数,后手就又删去一条边使得它又变成奇数
而如果先手面临的是偶数,那么再怎么都不会遇到最后为1的情况
此时后手就会想尽办法让你的状态变为奇数,可是他无能为力啊
code by std:
#include <cstdio>
int n, D[1000010];
int main() {
scanf("%d", &n);
for (int i = 1, u, v; i < n; ++i) {
scanf("%d%d", &u, &v); ++D[u], ++D[v];
}
for (int i = 1; i <= n; ++i)
if (!(D[i] & 1)) { puts("Alice"); return 0; }
puts("Bob"); return 0;
}
吐槽:
为什么过了大样例却wa了
分析:
此题的关键在于考虑每个元素的贡献,而不是考虑一个区间的贡献
code by std:
#include<bits/stdc++.h>
const int N=100001,p=1000000007;
int n,k,a[N],b[N],ans;
std::unordered_map<int,int>m;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
b[i]=i-m[a[i]];
m[a[i]]=i;
ans=(ans+(1LL*n*k%p-i+1+p)%p*b[i])%p;
}
for(int i=1;i<=n;++i){
if(b[i]==i)b[i]+=n-m[a[i]];
ans=(ans+(500000004LL*(k-1)%p*k%p*n%p-1LL*(k-1)*(i-1)%p+p)%p*b[i])%p;
}
printf("%d",ans);
}
题解:
分析:本题的关键在如何判断两条路径不会相交
还有就是可以不用差分,直接容斥一下就好
code by std:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=3005;
int n,p,q,cnte,head[N];
LL f[N][N],g[N][N],fp[N],fq[N],gp[N],gq[N],sump,sumq;
LL ans;
struct edge{int to,nxt;}e[N<<1];
void Add(int a,int b){
e[++cnte]=(edge){b,head[a]};
head[a]=cnte;
}
void dfs1(int x,int fa){
f[x][0]=1;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa)continue;
dfs1(y,x);
for(int j=1;j<=p;++j)fp[x]+=f[x][p-j]*f[y][j-1];
for(int j=1;j<=q;++j)fq[x]+=f[x][q-j]*f[y][j-1];
for(int j=1;j<=p;++j)f[x][j]+=f[y][j-1];
}
}
void dfs2(int x,int fa){
for(int j=1;j<=p;++j)gp[x]+=f[x][p-j]*g[x][j];
for(int j=1;j<=q;++j)gq[x]+=f[x][q-j]*g[x][j];
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa)continue;
g[y][1]=1;
for(int j=2;j<=p;++j)g[y][j]+=g[x][j-1]+f[x][j-1]-f[y][j-2];
dfs2(y,x);
}
}
int main(){
scanf("%d%d%d",&n,&p,&q);if(p<q)swap(p,q);
for(int i=1,a,b;i<n;++i){
scanf("%d%d",&a,&b);
Add(a,b);Add(b,a);
}
dfs1(1,0);dfs2(1,0);
for(int i=1;i<=n;++i){sump+=fp[i];sumq+=fq[i];}
ans=sump*sumq;
for(int i=1;i<=n;++i)ans-=fp[i]*fq[i]+fp[i]*gq[i]+fq[i]*gp[i];
printf("%lld",ans<<2);
return 0;
}
标签:cdn map can 差分 class 固定 put sum 分析
原文地址:https://www.cnblogs.com/wzxbeliever/p/11809037.html