CF 283C 坑死我了,半夜终于刷过,报告来了

来源:互联网 发布:1888端口被占用怎么办 编辑:程序博客网 时间:2024/04/29 01:03

CF283 C Coin Troubles

http://www.codeforces.com/problemset/problem/283/C

n中不同的硬币,但是他们的面值可能相同(其实无影响),有q个限制,某一种的数量要严格大于另外某一种。现在要凑成t面值,问有多少中方法,结果mod  1e9+7

首先应该想到没有q个限制的时候,是背包问题,可惜我这个背包我本来不会,后来看也没看懂,不知道是背包九讲中的哪一个。后来自己想了一下,相出了一个办法,和别人的代码一比较,发现是一样的,其实我想的办法就是背包的思路。分别用每一种硬币去更新凑成新面值的方案数,详情见代码。

问题是怎么把q个限制搞掉。

比如面值为a:1b2a要多余b,我们可以把b的值变成a+b=3,每次用一个b,就相当于ab一起用,这样就能保证a的数量永远大于等于b,那么题目要求严格大于,我们只需要在t里面减去一个a就可以了。这是两个硬币的关系,可以推到n个连续的关系上。

需要注意的是这些关系可能存在环,这样必然不能。

我是用双向链表写的dfs,比如有a>b>c>d ,那么深搜这条链,变成aa+ba+b+ca+b+c+d,然后t减去3*a+2*b+c,这里错了好久,在减的时候超过了int的下限,变成了正的,导致后面背包越界了,只要有一瞬间t<0了,答案就是0我就是被这里坑的!!!

贴代码

#include "iostream"#include "cstdio"#include "cstring"#include "cmath"#include "stdlib.h"#include "algorithm"using namespace std;int flag=1,n,q,t ;int f[100010];typedef struct node{    int val,from,to,vis;} NODE;NODE point[310];void dfs(int x){    point[x].vis=1;    if(point[x].to==0)        return;    point[point[x].to].val+=point[x].val;    dfs(point[x].to);    t-=point[x].val;    if(t<0)    flag=0;//就是这里坑了我一晚上,坑到晚上12点,终于在电脑没电前一小会AC了}int main(){    freopen("in.txt","r",stdin);    int x,y;    scanf("%d %d %d",&n,&q,&t);    memset(f,0,sizeof(f));    f[0]=1;    for(int i=1; i<=n; i++)    {        scanf("%d",&point[i].val);        point[i].from=point[i].to=point[i].vis=0;    }    for(int i=0; i<q; i++)    {        scanf("%d %d",&x,&y);        point[x].to=y;        point[y].from=x;    }    for(int i=1; i<=n; i++)        if(point[i].from==0)            dfs(i);    if(flag==0)    {        printf("0\n");        return 0;    }    for(int i=1; i<=n; i++)        if(point[i].vis==0)        {            printf("0\n");            return 0;        }    for(int i=1; i<=n; i++)        for(int j=0; j+point[i].val<=t; j++)        {            int tar=j+point[i].val;            int ftar=f[tar];            f[tar]=(f[tar]+f[j])%1000000007;        }    printf("%d\n",f[t]);    return 0;}

水平有限,众神轻喷。

原创粉丝点击