【题解】【CF283C Coin Troubles】
好坑的一道题。。。
Solution
首先很容易联想到完全背包计算方案数,考虑如何维护严格大于的限制。
把限制看作一条有向边,题目保证每个点入度,出度均不超过1,则最终的图一定是若干个链或环。若存在环一定无解。
那么对于每条链分别考虑,每条链中最小的点最少选0个,第二小的最少选1个,···第i小的最少选i-1个,先把这些必选的选完,直接在t里面扣即可。
然后对于任意一个点,若选一次这个点,必须把所有大于它的都选一次,因此,可以将必选同时选的物品打包,价值是一个后缀和,然后做完全背包即可。
但是一开始每想到环的情况。。。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') {w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=~(x-1);
if(x>9) write(x/10);
putchar('0'+x%10);
}
const int N=1e5+100,mod=1e9+7;
int a[305],t,w[305],f[N],cnt,sum,n,q,vis[305];
vector<int>v[305];
int ind[305];
void dfs(int x,int tot)
{
t-=tot*a[x];vis[x]=1;
if(v[x].size()==0){
sum+=a[x];w[++cnt]=sum;return;
}
dfs(v[x][0],tot+1);sum+=a[x];w[++cnt]=sum;
}
signed main()
{
n=read();q=read();t=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=q;++i)
{
int x=read(),y=read();
v[y].push_back(x);ind[x]++;
}
for(int i=1;i<=n;++i){
if(ind[i]==0){
sum=0;
dfs(i,0);
}
}
for(int i=1;i<=n;++i){
if(vis[i]==0){
puts("0");return 0;
}
}
if(t<0){
puts("0");return 0;
}
f[0]=1;
for(int i=1;i<=cnt;++i){
for(int j=w[i];j<=t;++j)
{
f[j]+=f[j-w[i]];f[j]%=mod;
}
}
write(f[t]);
return 0;
}

浙公网安备 33010602011771号