zoukankan      html  css  js  c++  java
  • 点亮灯笼

    题解:考虑题意,所修改的位置实际上是若干段,每段有一段或者两端可以修改。

    处于最左边和最右边的两端由于只能从一边开始点灯,因此方案数为1,而其余每一段内的方案数为2^(l-1)。

     其中只考虑每个区间都是从一端一直点燃到另一端。则方案数为(n-m!)/(p1!*p2!*p3!*.....*pk1),其中pi!表示第i端全排列,(n-m)!表示总区间的全排列。这只是一种情况,然后再乘以每个区间的方案数即为最终答案。

    ps:由于阶乘会导致最后的数非常大,因此可将其分解为质因子相乘的形式。除以的时候只需进行质因子的幂运算即可。最后将所有的质因子相乘。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define N 100100
    #define ll long long
    const int M=1e9+7;
    using namespace std;
    int n,m,sum(0),num(0);
    int dr[N],zs[N],ff[N];
    ll ans=1;
    bool f[N]={0};
    struct node
    {
        ll l,s;//l每一段区间的长度,s每一段区间的方案数 
    }la[N];
    void xx()//欧拉筛法求素数。背过模板就好了。 
    {
        for (int i=2;i<=n;i++)
          {
               if (!f[i]) zs[++num]=i;
             for (int j=1;j<=num,zs[j]*i<=n;j++)
                  {
                      f[zs[j]*i]=1;
                      if (!(i%zs[j])) break;    
                  } 
          }
    }
    ll jc(ll p,ll k)//快速幂 
    {
        ll ans=1;
        while (k)
          {
               if (k&1) ans=ans*p%M;
               p=p*p%M;
               k>>=1;
          }
        return ans;
    }
    int main()
    {
        freopen("lantern.in","r",stdin);
        freopen("lantern.out","w",stdout);
        
        scanf("%d%d",&n,&m);
        xx();
        for (int i=1;i<=m;i++) scanf("%d",&dr[i]);  
        sort(dr+1,dr+m+1);
        if (dr[1]>1)
          {
             la[++sum].l=dr[1]-1;
             la[sum].s=1;
          }
        if (dr[m]<n)
          {
               la[++sum].l=n-dr[m];
               la[sum].s=1;
          }
        for (int i=2;i<=m;i++)
          {
                if (dr[i]-dr[i-1]-1) 
                  {
                     la[++sum].l=dr[i]-dr[i-1]-1;
                   la[sum].s=jc(2,la[sum].l-1);    
                }
          }
           for (int i=1;i<=num;i++)//(n-m)!表示成质因子相乘的形式 
             {
             ll t=n-m;
             while (t)
               {
                     ff[i]+=t/zs[i];
                     t/=zs[i];
               }
          }
        for (int i=1;i<=sum;i++)//求出每个区间的全排列pi 
          for (int j=1;j<=num;j++)
            {
                ll t=la[i].l;
                while (t)
                  {
                       ff[j]-=t/zs[j];
                       t/=zs[j];
                  }
            }
            
        for (int i=1;i<=num;i++)
           ans=ans*jc(zs[i],ff[i])%M;
        for (int i=1;i<=sum;i++)
          ans=ans*la[i].s%M;
         cout<<ans<<endl;
         
         fclose(stdin);
         fclose(stdout);
         return 0; 
    }
    100
  • 相关阅读:
    基本算法2
    基本算法
    读书笔记 《跟老齐学python》
    python杂记 20200207 离线安装 正则
    傻傻分不清之 Cookie、Session、Token、JWT 转载:https://juejin.im/post/5e055d9ef265da33997a42cc
    并发相关 杂记
    原根
    POJ2749 Building roads
    luogu P4735 最大异或和
    SP913 QTREE2
  • 原文地址:https://www.cnblogs.com/sjymj/p/5994717.html
Copyright © 2011-2022 走看看