有$n$种转移装置,每种转移装置本质相同,每种装置可以前进$a_i$单位,但只有$b_i$个。

从初始坐标为$0$出发,途中不能经过$c_1,c2,...,c_m$中的任意一个点。

走到$\sum\limits_{i = 1}^n a_ib_i$位置的方案数$mod 10^9 + 7$的值。

对于$100\%$的数据满足$1 \leq n \leq 6 , 1 \leq m \leq 10^5 ,0<c_i < \sum\limits_{i = 1}^n a_ib_i$

  Solution : 

    由于每个装置本质相同,那么我们只需要记录当前使用的转移装置数作为状态即可。

    这样定义状态的总状态数时$\prod_{i = 1}^n b_i \leq 13^6 = 4826809$

    注意,由于有$m$点不能走,还需要开一个$hash$存当前值能不能走,特殊判掉即可。

    转移的时候枚举当前通过那个转移装置走到当前位置,转移时间复杂度为$O(n)$

    请注意,本题的模数为$10^8 + 7$,您是否数错了零?

    所以,本题的总时间复杂度是$O(n\prod\limits_{i=1}^{n} b_i)$

# pragma GCC optimize(3)
# include<bits/stdc++.h>
# define int long long
# define hash Hash
# define Rint register int
using namespace std;
const int mo=100000007;
int f[13][13][13][13][13][13];
struct rec{int a,b;}a[10];
int n,m;
vector<int>hash[10007];
inline int read() {
    int X=0,w=0; char c=0;
    while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
    while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
    return w?-X:X;
}
void insert(int key) {
    int k = key % 10007,sz = hash[k].size();
    for (int i=0;i<sz;i++) if (hash[k][i] == key) return;
    hash[k].push_back(key);
}
bool find(int key) {
    int k=key % 10007,sz = hash[k].size();
    for (int i=0;i<sz;i++) if (hash[k][i] == key) return true;
    return false;
}
signed main() {
    n=read();
    for (Rint i=1;i<=n;i++) {
        a[i].a=read(); a[i].b=read();
    }
    m=read();
    for (Rint i=1;i<=m;i++) {
        int t=read(); insert(t); 
    }
    f[0][0][0][0][0][0]=1;
    for (Rint a1=0;a1<=a[1].b;a1++) for (Rint a2=0;a2<=a[2].b;a2++)
    for (Rint a3=0;a3<=a[3].b;a3++) for (Rint a4=0;a4<=a[4].b;a4++)
    for (Rint a5=0;a5<=a[5].b;a5++) for (Rint a6=0;a6<=a[6].b;a6++) {
        int tmp = a1*a[1].a+a2*a[2].a+a3*a[3].a+a4*a[4].a+a5*a[5].a+a6*a[6].a;
        if (find(tmp)) {
            f[a1][a2][a3][a4][a5][a6]=0;
            continue;
        } 
        if (a1+1<=a[1].b) (f[a1+1][a2][a3][a4][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
        if (a2+1<=a[2].b) (f[a1][a2+1][a3][a4][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
        if (a3+1<=a[3].b) (f[a1][a2][a3+1][a4][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
        if (a4+1<=a[4].b) (f[a1][a2][a3][a4+1][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
        if (a5+1<=a[5].b) (f[a1][a2][a3][a4][a5+1][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
        if (a6+1<=a[6].b) (f[a1][a2][a3][a4][a5][a6+1]+=f[a1][a2][a3][a4][a5][a6])%=mo; 
    }
    printf("%lld\n",f[a[1].b][a[2].b][a[3].b][a[4].b][a[5].b][a[6].b]%mo);  
    return 0;
}
traveller.cpp

相关文章: