zoukankan      html  css  js  c++  java
  • BZOJ 3129 [SDOI2013]方程 (拓展Lucas)

    题目大意:给定一个方程$X_{1}+X_{2}+X_{3}+X_{4}+...+X_{n}=M$,$forall X_{i}<=A_{i} (i<=n1)$ $forall X_{i}>=A_{i} (n1<i<=n2)$在保证的合法整数解个数n1<=8,n2<=8

    一波三折的数学题,调了半天才发现我的Lucas是错的,但它竟然通过了洛谷那一道模板题的全部数据....

    后面n1~n2的部分很好处理,直接用M减掉这个部分就行了

    因为是求正整数解,所以这个组合数的形式可以用隔板法处理,即每两个物品之间设为一个空位,现在要分成n个部分,则把n-1个隔板放进空位

    即$C_{m-1}^{k-1}$

    前面1~n1的部分依然使用容斥的方法处理,类似于CF451E,状压+容斥

    接下来就是拓展Lucas了,讲解传送门

      1 #include <queue>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N 10
      7 #define ll long long
      8 using namespace std;
      9 
     10 ll exgcd(ll a,ll b,ll &x,ll &y){
     11     if(!b) {x=1,y=0;return a;}
     12     ll g=exgcd(b,a%b,x,y);
     13     ll t=x;x=y,y=t-a/b*y;
     14     return g;
     15 }
     16 ll qmul(ll x,ll y,const ll &mo){
     17     ll ans=0;
     18     while(y){
     19         if(y&1) ans=(ans+x)%mo;
     20         x=(x+x)%mo,y>>=1;
     21     }return ans;
     22 }
     23 ll qpow(ll x,ll y,const ll &mo){
     24     ll ans=1;
     25     while(y){
     26         if(y&1) ans=ans*x%mo;
     27         x=x*x%mo,y>>=1;
     28     }return ans;
     29 }
     30 ll son1[]={10007};
     31 ll son2[]={2,3,11,397,10007};
     32 ll son3[]={5,7,101};
     33 
     34 namespace exlucas{
     35 ll ans=0,M=1;
     36 ll son[10],pw[10];
     37 int num;
     38 void Pre(ll p)
     39 {
     40     if(p==10007){
     41         num=1,son[0]=son1[0],pw[0]=son1[0];
     42     }else if(p==262203414){
     43         num=5;
     44         for(int i=0;i<num;i++)
     45             son[i]=son2[i],pw[i]=son[i];
     46     }else{
     47         num=3;
     48         for(int i=0;i<num;i++)
     49             son[i]=son3[i];
     50         pw[0]=125,pw[1]=343,pw[2]=10201;
     51     }
     52 }
     53 int excrt_ins(ll A,ll B)
     54 {
     55     ll a=A,b=B,c=(a-ans%b+b)%b,x,y;
     56     ll g=exgcd(M,b,x,y);ll bg=b/g;
     57     if(c%g!=0) return -1;
     58     //x=x*(c/g)%bg;
     59     x=qmul(x,c/g,bg);
     60     ans+=x*M,M*=bg,ans=(ans%M+M)%M;
     61     return 1;
     62 }
     63 ll get_mul(ll n,ll p,ll &sum,const ll &mo,int type)
     64 {
     65     if(n==0) return 1;
     66     ll ans=1;
     67     for(int i=2;i<=min(n,mo);i++)
     68         if(i%p) ans=ans*i%mo;
     69     ans=qpow(ans,n/mo,mo);
     70     for(int i=2;i<=n%mo;i++)
     71         if(i%p) ans=ans*i%mo;
     72     sum+=1ll*(n/p)*type;
     73     return ans*get_mul(n/p,p,sum,mo,type)%mo;
     74 }
     75 ll get_C(ll n,ll m,ll p,const ll &mo)
     76 {
     77     if(m>n) return 0;
     78     ll sum=0;ll y;
     79     ll nn=get_mul(n,p,sum,mo,1);
     80     ll mm=get_mul(m,p,sum,mo,-1);
     81     ll nm=get_mul(n-m,p,sum,mo,-1);
     82     exgcd(mm,mo,mm,y);
     83     mm=(mm%mo+mo)%mo;
     84     exgcd(nm,mo,nm,y);
     85     nm=(nm%mo+mo)%mo;
     86     return nn*mm%mo*nm%mo*qpow(p,sum,mo)%mo;
     87 }
     88 ll C(ll n,ll m,const ll &mo)
     89 {
     90     if(m>n) return 0;
     91     ll ret=0;
     92     for(int i=0;i<num;i++){
     93         ll val=get_C(n,m,son[i],pw[i]);
     94         excrt_ins(val,pw[i]);
     95     }
     96     ret=ans,M=1,ans=0;
     97     return ret;
     98 }
     99 };
    100 
    101 int T;ll p;
    102 ll n,m,n1,n2;
    103 ll a[N],b[N];
    104 
    105 int main()
    106 {
    107    // freopen("t1.in","r",stdin);
    108     scanf("%d%lld",&T,&p);
    109     exlucas::Pre(p);
    110     while(T--)
    111     {
    112         scanf("%lld%lld%lld%lld",&n,&n1,&n2,&m);
    113         memset(a,0,sizeof(a));memset(b,0,sizeof(b));
    114         for(int i=0;i<n1;i++) scanf("%lld",&a[i]);
    115         for(int i=1;i<=n2;i++) scanf("%lld",&b[i]),m-=(b[i]-1);
    116         if(m<0) printf("0
    ");
    117         int tot=(1<<n1);ll ans=0;
    118         for(int s=0;s<tot;s++)
    119         {
    120             ll res=m;int cnt=0;
    121             for(int i=0;i<n1;i++) if(s&(1<<i)) res-=a[i],cnt++;
    122             if(res<=0) {continue;}
    123             ll w=(cnt&1?-1ll:1ll)*exlucas::C(res-1,n-1,p);
    124             (ans+=w)%=p;
    125         }
    126         printf("%lld
    ",(ans%p+p)%p);
    127     }
    128     return 0;
    129 }
  • 相关阅读:
    正则表达式语法
    javascript刷新页面方法
    数据表操作Sql语句
    UML中的关系讲解
    ASP.net和C#的MD5加密
    Excel导入数据库,兼容Excel2003,2007
    EXCEL文件导入数据库
    javascript 控制文本框输入格式
    键盘扫描码
    jquery在不同浏览器下的兼容性问题
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9891298.html
Copyright © 2011-2022 走看看