zoukankan      html  css  js  c++  java
  • 51nod部分容斥题解

    51nod1434 区间LCM

    跟容斥没有关系。首先可以确定的一个结论是:对于任意正整数,有1*2*...*n | (k+1)*(k+2)*...*(k+n)。因为这就是$C_{n+k}^{k}$。

    于是这题就有:m最多枚举到2n。

    于是有一个做法:对n!分解质因数,然后枚举m的同时统计已获得的所有质因数的次幂,全部不小于n!时即可推出。

    复杂度肯定不大于$O(nlog n)$。

    同时这里有一个不会证的结论:找到n以内最大的$p^k$的数(p是质数),答案就是$2p^k$。

    $O(nlog n)$

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=2000010;
    10 int T,n,tot,cnt[N],cnt2[N],pr[N],b[N],id[N];
    11 
    12 void init(int n){
    13     rep(i,2,n){
    14         if (!b[i]) pr[++tot]=i,id[i]=tot;
    15         for (int j=1; j<=tot && pr[j]*i<=n; j++){
    16             b[pr[j]*i]=1;
    17             if (i%pr[j]==0) break;
    18         }
    19     }
    20 }
    21 
    22 int main(){
    23     init(1000000);
    24     for (scanf("%d",&T); T--; ){
    25         scanf("%d",&n); int g=1;
    26         for (int i=1; i<=tot && pr[i]<=n; i++)
    27             for (int j=pr[i]; j<=n; j*=pr[i]) g=max(g,j);
    28         printf("%d
    ",g*2);
    29     }
    30     return 0;
    31 }
    51nod1434

    51nod1486 大大走格子

    先把所有坏点按曼哈顿距离排序。

    总方案数减去不合法方案的数量,枚举第一次走到的不合法格子(x,y),则答案就是(走合法格子到(x,y)的路径数)*C(n-x,m-y)。而走合法格子到(x,y)的路径数用同样的方法算即可。

    $O(n^2)$

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 using namespace std;
     5 
     6 const int N=200010,mod=1e9+7;
     7 int n,m,K,fac[N],inv[N],f[N];
     8 struct P{ int x,y; }p[N];
     9 bool operator <(const P &a,const P &b){ return (a.x==b.x) ? a.y<b.y : a.x<b.x; }
    10 int C(int n,int m){ return n<m ? 0 : 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod; }
    11 
    12 int ksm(int a,int b){
    13     int res=1;
    14     for (; b; a=1ll*a*a%mod,b>>=1)
    15         if (b & 1) res=1ll*res*a%mod;
    16     return res;
    17 }
    18 
    19 void init(int n){
    20     fac[0]=1; rep(i,1,n) fac[i]=1ll*fac[i-1]*i%mod;
    21     inv[n]=ksm(fac[n],mod-2);
    22     for (int i=n-1; ~i; i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    23 }
    24 
    25 int main(){
    26     scanf("%d%d%d",&n,&m,&K); init(n+m);
    27     rep(i,1,K) scanf("%d%d",&p[i].x,&p[i].y);
    28     sort(p+1,p+K+1); p[++K]=(P){n,m};
    29     rep(i,1,K){
    30         int res=C(p[i].x+p[i].y-2,p[i].x-1);
    31         rep(j,1,i-1) if (p[j].x<=p[i].x && p[j].y<=p[i].y)
    32             res=(res-1ll*f[j]*C(p[i].x-p[j].x+p[i].y-p[j].y,p[i].x-p[j].x)%mod+mod)%mod;
    33         f[i]=res;
    34     }
    35     printf("%d
    ",f[K]);
    36     return 0;
    37 }
    51nod1486

    51nod1678 lyk与gcd

    简单莫比乌斯容斥,答案是$sumlimits_{d|x}mu(d)sumlimits_{d|i}a[i]$。

    先线性筛出$mu$,再对每个d维护$sumlimits_{d|i}a[i]$,事先将每个数的因子全部预处理出来以减小常数。

    $O(n*n^frac{1.44}{ln ln n})$(据说n的因子个数是$n^frac{1.44}{ln ln n}$级别的,当然肯定不满)

     1 #include<vector>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 typedef long long ll;
     6 using namespace std;
     7 
     8 const int N=200010;
     9 int n,Q,tot,op,x,k,a[N],sm[N],miu[N],pr[N],b[N];
    10 vector<int>ve[N];
    11 
    12 void init(int n){
    13     rep(i,2,n){
    14         if (!b[i]) pr[++tot]=i,miu[i]=-1;
    15         for (int j=1; j<=tot && pr[j]*i<=n; j++){
    16             b[pr[j]*i]=1;
    17             if (i%pr[j]==0) { miu[pr[j]*i]=0; break; }
    18                 else miu[pr[j]*i]=-miu[i];
    19         }
    20     }
    21     rep(i,1,n) for (int j=i; j<=n; j+=i) ve[j].push_back(i);
    22 }
    23 
    24 int main(){
    25     scanf("%d%d",&n,&Q); miu[1]=1; init(100000);
    26     rep(i,1,n){
    27         scanf("%d",&a[i]); int ed=ve[i].size()-1;
    28         rep(j,0,ed) sm[ve[i][j]]+=a[i];
    29     }
    30     rep(i,1,Q){
    31         scanf("%d",&op);
    32         if (op==1){
    33             scanf("%d%d",&x,&k); int ed=ve[x].size()-1;
    34             rep(i,0,ed) sm[ve[x][i]]+=k-a[x];
    35             a[x]=k;
    36         }else{
    37             scanf("%d",&x); int ed=ve[x].size()-1; ll res=0;
    38             rep(i,0,ed) res+=sm[ve[x][i]]*miu[ve[x][i]];
    39             printf("%lld
    ",res);
    40         }
    41     }
    42     return 0;
    43 }
    51nod1678

    51nod1406 与查询

    比较巧妙的DP,具体见代码。注意这题需要快速读入与输出。

    $O(Alog A)$

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=1000010;
    10 int n,x,mx,ww[30],f[N];
    11 
    12 inline void rd(int &x){
    13     x=0; char ch=getchar();
    14     while (ch<'0' || ch>'9') ch=getchar();
    15     while (ch>='0' && ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    16 }
    17 
    18 inline void pr(int x){
    19     int tot=0;
    20     if (!x) { putchar('0'); return; }
    21     while (x) ww[++tot]=x%10,x/=10;
    22     while (tot) putchar(ww[tot--]+'0');
    23 }
    24 
    25 int main(){
    26     rd(n);
    27     rep(i,1,n) rd(x),mx=max(mx,x),f[x]++;
    28     for (int i=1; i<=mx; i<<=1)
    29         for (int j=mx; j; j--) if (i&j) f[j-i]+=f[j];
    30     rep(i,0,1000000) pr(f[i]),putchar('
    ');
    31     return 0;
    32 }
    51nod1406

    51nod1407 与与与与

    考虑容斥,求“相邻后至少k位为1”的方案数f(x),答案就是$2^{f(x)}-1$。求f(x)就是上一道题。

    $O(Alog A)$

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=1000010,mod=1e9+7;
    10 int n,x,mx,ans,f[N];
    11 
    12 int ksm(int a,int b){
    13     int res=1;
    14     for (; b; a=1ll*a*a%mod,b>>=1)
    15         if (b & 1) res=1ll*res*a%mod;
    16     return res;
    17 }
    18 
    19 int Cnt(int x){
    20     int res=1;
    21     for (; x; x>>=1) if (x&1) res=-res;
    22     return res;
    23 }
    24 
    25 int main(){
    26     while (~scanf("%d",&n)){
    27         rep(i,0,mx) f[i]=0; mx=ans=0;
    28         rep(i,1,n) scanf("%d",&x),mx=max(mx,x),f[x]++;
    29         for (int i=1; i<=mx; i<<=1)
    30             for (int j=mx; j; j--) if (i&j) f[j-i]+=f[j];
    31         rep(i,0,mx) ans=(ans+Cnt(i)*(ksm(2,f[i])-1))%mod;
    32         printf("%d
    ",(ans+mod)%mod);
    33     }
    34     return 0;
    35 }
    51nod1407

    51nod1667 概率好题

    好题。https://blog.csdn.net/samjia2000/article/details/53025218

    $O(2^{k1+k2})$

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 using namespace std;
     6 
     7 const int N=20,mod=1e9+7;
     8 int T,n,m,l,r,s,sm,ans1,ans2,ans3,len[N];
     9 
    10 int ksm(int a,int b){
    11     int res=1;
    12     for (; b; a=1ll*a*a%mod,b>>=1)
    13         if (b & 1) res=1ll*res*a%mod;
    14     return res;
    15 }
    16 
    17 int C(int n,int m){
    18     if (n<m) return 0;
    19     int res=1;
    20     rep(i,1,m) res=1ll*res*(n-m+i)%mod*ksm(i,mod-2)%mod;
    21     return res;
    22 }
    23 
    24 void dfs(int x,int t,int d){
    25     if (x>n+m){
    26         ans1=(ans1+1ll*t*C(sm-d+n+m-1,n+m)+mod)%mod;
    27         ans2=(ans2+1ll*t*C(sm-d+n+m-1,n+m-1)+mod)%mod;
    28         return;
    29     }
    30     dfs(x+1,t,d); dfs(x+1,-t,d+len[x]);
    31 }
    32 
    33 int main(){
    34     for (scanf("%d",&T); T--; ){
    35         scanf("%d",&n); s=1; sm=ans1=ans2=0;
    36         rep(i,1,n) scanf("%d%d",&l,&r),sm+=r,len[i]=r-l+1,s=1ll*s*len[i]%mod;
    37         scanf("%d",&m);
    38         rep(i,1,m) scanf("%d%d",&l,&r),sm-=l,len[i+n]=r-l+1,s=1ll*s*len[i+n]%mod;
    39         dfs(1,1,0); ans3=(1ll*s-ans1-ans2+mod+mod)%mod; s=ksm(s,mod-2);
    40         ans1=1ll*ans1*s%mod; ans2=1ll*ans2*s%mod; ans3=1ll*ans3*s%mod;
    41         printf("%d %d %d
    ",ans1,ans2,ans3);
    42     }
    43     return 0;
    44 }
    51nod1667
  • 相关阅读:
    非重复随机序列生成算法
    IE浏览器整页截屏程序
    地铁线路图的设计与实现
    拓扑排序算法的一个应用
    洛谷 P4450 双亲数
    洛谷 P2183 [国家集训队]礼物
    洛谷 P4159 [SCOI2009]迷路
    CF86D Powerful array
    Catalan数
    SP3266 KQUERY Kquery
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10022286.html
Copyright © 2011-2022 走看看