zoukankan      html  css  js  c++  java
  • [dfs][exgcd][容斥原理] Jzoj P5796 划分

    Description

    有一个未知的序列x,长度为n。它的K-划分序列y指的是每连续K个数的和得到划分序列,y[1]=x[1]+x[2]+....+x[K],y[2]=x[K+1]+x[K+2]+....+x[K+K]....。若n不被K整除,则y[n/K+1]可以由少于K个数加起来。比如n=13,K=5,则y[1]=x[1]+...+x[5],y[2]=x[6]+....+x[10],y[3]=x[11]+x[12]+x[13]。若小A只确定x的K[1]划分序列以及K[2]划分序列....K[M]划分序列的值情况下,问她可以确定x多少个元素的值。
     

    Input

    第一行输入两个正整数n,M。
    第二行输入M个正整数表示K[1],K[2].....K[M]。

    Output

    输出1个整数,表示能确定的元素
     

    Sample Input

    【输入样例1】
    3 1
    2
    【输入样例2】
    6 2
    2 3
    【输入样例3】
    123456789 3
    5 6 9

    Sample Output

    【输出样例1】
    1
    【输出样例2】
    2
    【输出样例3】
    10973937
     

    Data Constraint

    对于20%的数据,3 <= N <= 2000,M<=3。
    对于40%的数据,3 <= N <= 5*10^6。
    对于100%的数据,3 <= N <= 10^9 , 1 <= M <= 10,2 <= K[i] < N。
     

    Hint

    【样例1解释】
    小A知道x的2-划分序列,即分别知道x[1]+x[2],x[3]的值。
    小A可以知道x[3]的值。
    【样例2解释】
    小A知道x的2-划分序列,即分别知道x[1]+x[2],x[3]+x[4],x[5]+x[6] 的值。
    小A知道x的3-划分序列,即分别知道x[1]+x[2]+x[3] ,x[4]+x[5]+x[6] 的值。
    小A可以知道x[3],x[4]的值,个数为2.

    题解

    • 首先,如果x[p]能算出来,对于一组(i,j),必存在P%k[i]=0,P%k[j]=1
    • 也就是a1*k[i]-a2*k[j]=1,这个显然可以用扩展欧几里得来求解,且要满足gcd(k[i],k[j])=1
    • 然后这样的话,会出现重复计算,考虑容斥
    • 容斥系数就是子数的奇偶性
    • 观察一下式子:
      P mod k[i1]=0,P mod k[i2]=0,P mod k[i3]=0, ……
    • P mod k[j1]=1,P mod k[j2]=1,P mod k[j3]=1, ……
    • 其实等价于P mod lcm(k[i1],k[i2]...)=0 P mod lcm(k[j1],k[j2...)==1
    • 这个可以用扩展欧几里得来解,然后对于一组解的可求出P的方案数为kix[1,n]的个数
    • 还要特殊判断n的位置

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 using namespace std;
     5 int i,n,m,k[12];
     6 long long d,x,y,ans;
     7 void exgcd(long long a,long long b,long long &d,long long &x,long long &y)
     8 {
     9     if (!b) d=a,x=1,y=0; 
    10     else exgcd(b,a%b,d,y,x),y=y-x*(a/b);
    11 }
    12 long long gcd(long long x,long long y) { return y?gcd(y,x%y):x; }
    13 long long lcm(long long x,long long y) { return x*y/gcd(x,y); }
    14 void dfs(int t,long long tot1,long long tot2,long long x1,long long x2,long long w)
    15 {
    16     if (x1>n||x2>n) return;
    17     if (t>m)
    18     {
    19         if (tot1==0||tot2==0) return;
    20         exgcd(x1,x2,d,x,y);
    21         if (d<0) x=-x,y=-y,d=-d; 
    22         if (d>1) return;
    23         x=(x%x2+x2)%x2;
    24         ans+=w*((1LL*n/x1-x)/x2+(x1*x<=n));
    25         return;
    26     }
    27     dfs(t+1,tot1,tot2,x1,x2,w);
    28     dfs(t+1,tot1+1,tot2,lcm(x1,k[t]),x2,-w);
    29     dfs(t+1,tot1,tot2+1,x1,lcm(x2,k[t]),-w);
    30 }
    31 int main()
    32 {
    33     freopen("sazetak.in","r",stdin);
    34     freopen("sazetak.out","w",stdout);
    35     scanf("%d%d",&n,&m);
    36     for (int i=1;i<=m;i++) scanf("%d",&k[i]);
    37     k[++m]=n;
    38     dfs(1,0,0,1,1,1);
    39     printf("%lld",ans);
    40     return 0;
    41 }
  • 相关阅读:
    通过反射获取Android通知栏高度
    Android 的EditText实现不可编辑
    Android 代码混淆、第三方平台加固加密、渠道分发 完整教程(图文)
    eclipse、myeclipse,svn插件subclipse 忘记密码的解决方法(win7、win8、xp)
    Eclipse 基于接口编程的时候,快速跳转到实现类的方法(图文)
    WIN7、WIN8 右键在目录当前打开命令行Cmd窗口(图文)
    eclipse,myeclipse开发环境下,maven远程部署到tomcat7服务器(图文)
    python之路——博客目录
    生成器和协程 —— 你想知道的都在这里了
    python3.7导入gevent模块报错的解决方案
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9457102.html
Copyright © 2011-2022 走看看