题意:长度为1的01序列,其中有m个1,每次操作可以将某个1旁边的0改成1,求方案数,对10^9+7取模
/* 又是一道数论,没想出正解来,打了个暴力 这个题可以等价于给出一个01序列,每次可以把某个1旁边的0变成1,直到序列全部为1。那么我们可以把这个序列以初始的1为分界点分成若干段num,每一段的取的方案数是2^(len-1)(除了第一段和最后一段之外,第一段和最后一段是1),那么现在的问题就变成了从num段中每次取一个的方案数,是n!,因为里面有重复的,所以变成 num!/(len1!*len2!* …… *) 。 答案就是 fangan1*fangan2*……*num!/(len1!*len2!* …… *)。 至于有除法的mod,不会逆元,用质因数分解做的,这里涉及到分解 n!的一个定理: 当第i个素数为P 时,c[i]= n/p+n/(p*p)+n/(p*p*p)……(直到n/(p*……*p变成0) */#include#include #define N 100010#define ll long long#define mod 1000000007using namespace std;ll len[N],prime[N],c[N],num,vis[N],f[N],n,m,ans=1;ll pow(ll x,ll y){ ll tot=1; for(ll i=1;i<=y;i++)tot*=x,tot%=mod; return tot;}void j1(ll x){ for(ll i=1;i<=num;i++) { ll P=prime[i]; while(P<=n) { c[i]+=x/P; P*=prime[i]; } }}void j2(ll x){ for(ll i=1;i<=num;i++) { ll P=prime[i]; while(P<=n) { c[i]-=x/P; P*=prime[i]; } }}void Prime(){ for(int i=2;i<=n;i++) if(!f[i]) { prime[++num]=i; for(int j=2;i*j<=n;j++) f[i*j]=1; }}int main(){ //freopen("jh.in","r",stdin); freopen("lantern.in","r",stdin); freopen("lantern.out","w",stdout); cin>>n>>m; for(ll i=1;i<=m;i++) { ll x;cin>>x; vis[x]=1; } ll sum=0;vis[n+1]=1; for(ll i=1;i<=n+1;i++) if(vis[i])len[++len[0]]=sum,sum=0; else sum++; Prime();j1(n-m); for(int i=1;i<=len[0];i++) j2(len[i]); for(int i=2;i