• [容斥][数论]JZOJ 5796 划分


    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.

    分析

    我们发现其实对于一个可以被识别的p(位置),一定有一对(i,j)

    p%k[i]=0,p%k[j]=1

    也就是:a*k[i]+b*k[j]=1 (mod p)这样一个同余方程

    那么我们只要去重就行了,考虑容斥

    那么两个互不相干的集合s1,s2的方程如下:

    p%s1[0]=0 p%s1[1]=0 p%s1[2]=0 ...

    p%s2[0]=1 p%s2[1]=1 p%s2[2]=1 ...

    整个同余方程组可以整合为:a*lcm(|s1|)+b*lcm(|s2|)=1 (mod p),容斥系数为(-1)|s1|+|s2|

    然后这个同余方程在题目范围内的解数为:(n div lcm(|s1|-a+lcm(|s2|))/|s2|(a为正整数且<n)

    然后枚举时注意一下lcm(|s1|)和lcm(|s2|)都不能大于n,gcd(lcm(|s1|),lcm(|s2|))要等于1才有解

    各种零注意判断一下

    #pragma GCC optimize(3)
    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    int m;
    ll n;
    ll a[12];
    ll ans;
    
    inline ll Exgcd(ll a,ll b,ll &x,ll &y) {
        if (!b) {
            x=1;y=0;
            return a;
        }
        int ret=Exgcd(b,a%b,y,x);
        y-=a/b*x;
        return ret;
    }
    
    inline ll Lcm(ll a,ll b) {
        if (!a) return b;
        if (!b) return a;
        ll x,y;
        return a*b/Exgcd(a,b,x,y);
    }
    
    inline void Solve(int dep,ll s1,ll s2,int cnt) {
        if (s1>n||s2>n) return;
        if (dep==m) {
            if (s1==0||s2==0) return;
            ll x,y;
            if (Exgcd(s1,s2,x,y)!=1) return;
            x=(x%s2+s2)%s2;
            ans+=(cnt%2?-1ll:1ll)*(n/s1-x+s2)/s2;
            return;
        }
        Solve(dep+1,Lcm(s1,a[dep]),s2,cnt+1);
        Solve(dep+1,s1,Lcm(s2,a[dep]),cnt+1);
        Solve(dep+1,s1,s2,cnt);
    }
    
    int main() {
        freopen("sazetak.in","r",stdin);
        freopen("sazetak.out","w",stdout);
        scanf("%lld%d",&n,&m);
        for (register int i=0;i<m;i++) scanf("%lld",&a[i]);
        a[m++]=n;
        Solve(0,0,0,0);
        printf("%lld",ans);
        fclose(stdin);fclose(stdout);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    富文本编辑器 ueditor
    防抖和节流 lodash插件
    lodash
    awesome
    怎么在移动端模拟pc端进行web开发调试日志
    添加水印
    node.js取参四种方法req.body,req.params,req.param,req.body
    插件包
    python——Scrapy框架简介、内置选择器、管道文件、爬虫模块中的spider类
    python——BeautifulSoup4解析器,JSON与JsonPATH,多线程爬虫,动态HTML处理
  • 原文地址:https://www.cnblogs.com/mastervan/p/9457352.html
Copyright © 2020-2023  润新知