zoukankan      html  css  js  c++  java
  • [SCOI2010]幸运数字

    题目描述

    在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6,8,66,68,86,88),于是他又定义了一种“近似幸运号码”。lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如12,16,666都是“近似幸运号码”。

    现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。

    输入输出格式

    输入格式:

    输入数据是一行,包括2个数字a和b

    输出格式:

    输出数据是一行,包括1个数字,表示在闭区间[a, b]内“近似幸运号码”的个数

    输入输出样例

    输入样例#1:
    1 10
    输出样例#1:
    2

    说明

    对于30%的数据,保证1<=a<=b<=1000000

    对于100%的数据,保证1<=a<=b<=10000000000

    题解:

    容斥原理+dfs

    存在左界不难,只要容斥时减去左边的伪幸运数,假设要求[a,b],其中一个因数为p1

    只要由b/p1->b/p1-(a-1)/p1

    首先dfs求出所有幸运数字,

    总方案ans=(b/p1-(a-1)/p)+(b/p2-(a-1)/p)+...-(b/p1p2-(a-1)/p1p2)-......

    不过直接dfs显然超时

    优化:

    1.减小搜索范围,根据容斥原理,可以知道当px|py时,py与px显然重合且py无用,直接去掉,形成新的幸运数组

    2.时刻判断lcm(s,x)是否超过r,超过则不选该数x,记住判断时由于数太大,可能会溢出,所以要把判断换一下

     s*x/gcd(s,x)<=r ->s/gcd(s,x)<=(double)r/x这里的double是为防止整形判断有误(应该不会错,但会慢一点)

    3.完成以上2步应该是60分,还有关键一点:调整搜索顺序

    显然先从大的幸运数开始容斥,会在开始时产生较少的分支,而搜索算法的搜索树靠近根的分支越少就越快

    所以将幸运数重新排序就可以AC了,比原来快的多

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long lol;
     8 lol luck[3001],l,r,ans;
     9 int cnt;
    10 bool cmp(lol a,lol b)
    11 {
    12     return a>b;
    13 }
    14 void dfs_pre(lol s)
    15 {
    16     if (s>r) return;
    17     if (s)
    18     {
    19     cnt++;
    20     luck[cnt]=s;
    21     }
    22     dfs_pre(s*10+6);
    23     dfs_pre(s*10+8);
    24 }
    25 lol gcd(lol a,lol b)
    26 {
    27     if (!b) return a;
    28     return gcd(b,a%b);
    29 }
    30 void dfs(int x,lol s,int f)
    31 {
    32     if (x==0)
    33     {
    34         ans+=f*(r/s-(l-1)/s);
    35         return;
    36     }
    37      lol g=gcd(s,luck[x]);    
    38      if ((double)s/(double)g<=(double)r/(double)luck[x]) dfs(x-1,s/g*luck[x],f*(-1));
    39      dfs(x-1,s,f);
    40 }
    41 int main()
    42 {int i,j;
    43     cin>>l>>r;
    44      dfs_pre(0);
    45      for (i=1;i<=cnt;i++)
    46      {
    47          for (j=1;j<i;j++)
    48           if (luck[j]!=-1&&luck[i]%luck[j]==0)
    49             luck[i]=-1;
    50      }
    51       sort(luck+1,luck+cnt+1,cmp);
    52       for (i=cnt;i>=1;i--)
    53       if (luck[i]==-1) cnt--;
    54       sort(luck+1,luck+cnt+1);
    55     dfs(cnt,1,-1);
    56     cout<<r-l+1+ans;
    57 }
  • 相关阅读:
    解决淘淘第三天无法显示图片
    包名与工程名
    明明有这个类却提示出错
    出错,网页显示不出内容
    配置域名
    本地jar包添加到maven仓库
    POJ1704 Georgia and Bob 博弈论 尼姆博弈 阶梯博弈
    POJ 2960 S-Nim 博弈论 sg函数
    sg函数总结
    POJ 2425 A Chess Game 博弈论 sg函数
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7275512.html
Copyright © 2011-2022 走看看