一月の题
麻了一月都快结束了题也做了一些了却没写这个,更十倍了。
[ABC154F] Many Many Paths
组合数,挺简单
先鸽了
CF1542D
dp,转换一下题意,我们珂以看作是对于每一个 有多少个子序列能加上他的贡献。我们考虑一个 的贡献能被加上要满足有比它小的 操作,那么我们珂以不管操作的具体大小而是关心它们的大小关系。我们先枚举考虑的第 个操作 ,设 表示前 个操作中有 个加操作比 小时的子序列数,然后珂以分类讨论转移。
AT_tenka1_2017_f
这个数论题洛谷写了题解了自己看,还有些不懂的记得补。
P5505
直接求合法方案数求不出来,考虑转换成补集,用总方案数(盒子可以有空的)减去不合法方案数(盒子一定有空的)。总方案数简单,就是 。然后分开考虑当有 个盒子为空时对总方案数的贡献。设当前空的盒子有 个,相当于把球放进 个盒子中,只算这个 的贡献就是 ,根据乘法原理并且盒子是是有标号的,那么有 个盒子为空时的总贡献就是 ,注意这里是不能直接总的减去前面式子的,因为大的 的贡献中含有 小的 的贡献,你相当于重复减去了很多 的贡献。正确的做法是考虑容斥,设空盒子有 个时的贡献为 ,答案 ,即
还有需要预处理组合数。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=114514,M=1919810,mod=1e9+7;
ll n,m,a[N],inv[N];
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll C(ll n,ll m){
ll ans=1,res=1;
for(int i=m+1;i<=n;++i) ans=ans*i%mod;
for(int i=1;i<=n-m;++i) res=res*i%mod;
return ans*qpow(res,mod-2)%mod;
}
ll ans,res,f[2005][2005];
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;++i) cin>>a[i];
for(int i=0;i<=2000;++i) f[i][0]=f[i][i]=1;
for(int i=1;i<=2000;++i)
for(int j=1;j<=i;++j)
f[i][j]=(f[i-1][j-1]+f[i-1][j])%mod;
for(int i=0;i<n;++i){
res=qpow(-1,i)*f[n][i]%mod;
for(int j=1;j<=m;++j)
res=res*f[n-i+a[j]-1][n-i-1]%mod;
ans=((ans+res)%mod+mod)%mod;
}
cout<<ans;
return 0;
}
P4113
数据范围 ,那么莫队还是死了,需要严格 的做法。首先把询问按 排序离线搞没问题,然后我们考虑每个点对后面和他颜色相同的点的贡献,第一次出现这个颜色 时对答案无贡献,第二次才有,所以我们考虑记录每个点 前一个和他颜色相同的点 和 前一个点的前一个点,这样子类似于上一道题,我们用树状数组维护贡献,update(las[i],1),update(las[las[i]],-1)
,推理过程也和上一道题一样,注意可能会对 加减贡献,要直接 return。
注:上一道题是P1972,数据结构做题记录里有。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=114514,M=2*1919810;
ll n,cl,m,a[M],ans[M];
ll las[M],lasc[M];
ll c[M];
ll lowbit(ll x){return x&-x;}
void update(ll x,ll k){
if(!x) return;
while(x<=n){
c[x]+=k;
x+=lowbit(x);
}
}
ll query(ll x){
if(!x) return 0;
ll ans=0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
struct que{
ll l,r,id;
}q[M];
bool cmp(que x,que y){
return x.r<y.r;
}
//这个维护挺智慧的
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>cl>>m;
for(int i=1;i<=n;++i){
cin>>a[i];
las[i]=lasc[a[i]];
lasc[a[i]]=i;
}
for(int i=1;i<=m;++i) cin>>q[i].l>>q[i].r,q[i].id=i;
sort(q+1,q+m+1,cmp);
ll pos=1;
for(int i=1;i<=n;++i){
update(las[i],1),update(las[las[i]],-1);
while(q[pos].r==i&&pos<=m){
ans[q[pos].id]=query(q[pos].r)-query(q[pos].l-1);
++pos;
}
}
for(int i=1;i<=m;++i) cout<<ans[i]<<'\n';
return 0;
}