zoukankan      html  css  js  c++  java
  • 幸运数字(容斥原理+高精度与低精度的加 减 除)

    幸运数字

    题目描述:
    LYK 最近运气很差,例如在 NOIP 初赛中仅仅考了 90 分,刚刚卡进复赛,于是它决定使用一些方法来增加自己的运气值。
    它觉得,通过收集幸运数字可以快速的增加它的 RP 值。
    它给幸运数字下了一个定义:如果一个数 x 能被 3 整除或被 5 整除或被 7 整除,则这个数为幸运数字。
    于是它想让你帮帮它在 L~R 中存在多少幸运数字。
    输入格式:
    第一行两个数 L,R。
    输出格式:
    一个数表示答案。
    输入样例
    10 15
    输出样例
    4
    数据范围:
    对于 50%的数据 1<=L<=R<=10^5。
    对于 60%的数据 1<=L<=R<=10^9。
    对于 80%的数据 1<=L<=R<=10^18。
    对于 90%的数据 1<=L<=R<=10^100。
    对于另外 10%的数据 L=1, 1<=R<=10^100。
    对于 100%的数据 L, R 没有前导 0。
    思路:
    容斥原理
    设num(n,i)表示1~n中是i的倍数
    则求1~n中3或5或7的倍数为
    num(n,3)+num(n,5)+num(n,7)-num(n,3*5)-num(n,3*7)-num(5*7)+num(n,3*5*7)
    这样求出1~r的减去1~l-1的即可
    高精度!!!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=1010;
    int len,a[maxn],b[maxn],t[maxn],ans[maxn];
    int sa[maxn],sb[maxn],c[2]={1,1};
    char s1[maxn],s2[maxn];
    void jian2(int *a,int *b)
    {
        memset(sa,0,sizeof(sa));
        memset(sb,0,sizeof(sb));
        sa[0]=a[0];
        for(int i=1;i<=a[0];i++)
        sa[i]=a[a[0]-i+1];
        for(int i=1;i<=b[0];i++)
        sb[i]=b[b[0]-i+1];
        int len=1;
        while(len<=sa[0])
        {
            sa[len]=sa[len]-sb[len];
            if(sa[len]<0)
            {
                sa[len]=sa[len]+10;
                sa[len+1]--;
            }
            len++;
        }
        while(sa[0]>1&&!sa[a[0]])
        sa[0]--;a[0]=sa[0];
        for(int i=1;i<=sa[0];i++)
        a[i]=sa[sa[0]-i+1];
    }
    void div(int *r,int *a,int x)
    {
        int s=0;r[0]=a[0];
        for(int i=1;i<=a[0];i++)
        {
            s=s*10+a[i];
            r[i]=s/x;
            s=s%x;
        }
    }
    void add(int *a,int *b)
    {
        memset(sa,0,sizeof(sa));
        memset(sb,0,sizeof(sb));
        int len1=a[0],len2=b[0],len=1;
        for(int i=1;i<=len2;i++)
        sb[i]=b[len2-i+1];
        while(len<=len1||len<=len2)
        {
            sa[len]+=a[len]+sb[len];
            sa[len+1]=sa[len]/10;
            sa[len]=sa[len]%10;
            len++;
        }
        while(len>1&&!sa[len])
        len--;sa[0]=len;
        for(int i=0;i<=sa[0];i++) a[i]=sa[i];
    }
    void jian(int *a,int *b)
    {
        memset(sb,0,sizeof(sb));
        for(int i=1;i<=b[0];i++)
        sb[i]=b[b[0]-i+1];
        int len=1;
        while(len<=a[0])
        {
            a[len]=a[len]-sb[len];
            if(a[len]<0)
            {
                a[len]=a[len]+10;
                a[len+1]--;
            }
            len++;
        }
        while(a[0]>1&&!a[a[0]])
        a[0]--;
    }
    int main()
    {
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout);
        cin>>s1>>s2;
        int l1=strlen(s1),l2=strlen(s2);
        a[0]=l1,b[0]=l2;
        for(int i=1;i<=l1;i++) a[i]=s1[i-1]-'0'; 
        for(int i=1;i<=l2;i++) b[i]=s2[i-1]-'0';
        jian2(a,c);
        div(t,b,3);add(ans,t);
        div(t,b,5);add(ans,t);
        div(t,b,7);add(ans,t);
        div(t,a,3*5);add(ans,t);
        div(t,a,3*7);add(ans,t);
        div(t,a,5*7);add(ans,t);
        div(t,b,3*5*7);add(ans,t);
        div(t,b,3*5);jian(ans,t);
        div(t,b,3*7);jian(ans,t);
        div(t,b,5*7);jian(ans,t);
        div(t,a,3);jian(ans,t);
        div(t,a,5);jian(ans,t);
        div(t,a,7);jian(ans,t);
        div(t,a,3*5*7);jian(ans,t);
        for(int i=ans[0];i>=1;i--)
        cout<<ans[i];
        fclose(stdin);fclose(stdout);
        return 0;
    }
  • 相关阅读:
    RPM包校验和提取
    RPM包查询
    Find命令简介
    无法启动配置好的虚拟机
    文档发布至博客操作说明
    VMware Virtual Machine安装报错解决1
    python create home dircetory
    Centos7/Active Directory authentication using nss-pam-ldapd
    java try后面括号的作用
    vps上搭建jupyter notebook远程服务
  • 原文地址:https://www.cnblogs.com/cax1165/p/6070894.html
Copyright © 2011-2022 走看看