zoukankan      html  css  js  c++  java
  • BZOJ 1853: [Scoi2010]幸运数字(容斥原理)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1853

    题意:

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

    思路:

    首先要明白一点的是,在N范围内找a或b的倍数的个数为:

    那么推广到这题的话也是差不多的,也就是容斥原理的运用。

    首先可以先找出所有带6、8的数,可以优化一下删去有倍数关系的数,然后就是从中找lcm,也就是容斥原理的奇加偶减。在寻找的过程中,优先找值大的,这样一来剪枝会剪得更多一些。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<sstream>
     6 #include<vector>
     7 #include<stack>
     8 #include<queue>
     9 #include<cmath>
    10 #include<map>
    11 #include<set>
    12 using namespace std;
    13 typedef long long ll;
    14 typedef pair<int,int> pll;
    15 const int INF = 0x3f3f3f3f;
    16 const int maxn = 1e5 + 5;
    17 
    18 int n;
    19 ll l, r;
    20 ll cnt;
    21 ll ans;
    22 ll a[maxn];
    23 ll b[maxn];
    24 int vis[maxn];
    25 
    26 void init(ll x)
    27 {
    28     if(x>r)  return;
    29     if(x!=0)  a[cnt++]=x;
    30     init(x*10+6);
    31     init(x*10+8);
    32 }
    33 
    34 ll gcd(ll a, ll b)
    35 {
    36     return b==0?a:gcd(b,a%b);
    37 }
    38 
    39 void dfs(int cur, int cnt, ll val)
    40 {
    41     if(cur>=n)
    42     {
    43         if(!cnt)  return;
    44         if(cnt&1)   ans+=(r/val-(l-1)/val);
    45         else ans-=(r/val-(l-1)/val);
    46         return;
    47     }
    48     dfs(cur+1,cnt,val);
    49     ll tmp=val/(gcd(a[cur],val));  
    50     if((double)tmp*a[cur]<=r)
    51     {
    52         dfs(cur+1,cnt+1,tmp*a[cur]);
    53     }
    54 }
    55 
    56 int main()
    57 {
    58     //freopen("in.txt","r",stdin);
    59     while(~scanf("%lld%lld",&l,&r))
    60     {
    61         cnt=0;
    62         init(0);
    63 
    64         n=0;
    65         sort(a,a+cnt);
    66         memset(vis,0,sizeof(vis));
    67         for(int i=0;i<cnt;i++)
    68         {
    69             if(!vis[i])
    70             {
    71                 b[n++]=a[i];
    72                 for(int j=i+1;j<cnt;j++)
    73                 {
    74                     if(a[j]%a[i]==0)
    75                         vis[j]=1;
    76                 }
    77             }
    78         }
    79         for(int i=0;i<n;i++)
    80             a[i]=b[n-i-1];
    81 
    82         ans=0;
    83         dfs(0,0,1);
    84         printf("%lld
    ",ans);
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    linux tcpdump(转)
    linux ping
    Dalvik VM和JVM 的比较
    Android应用开发基础之八:广播与服务(二)
    Android应用开发基础之七:广播与服务(一)
    Android应用开发基础之五:网络编程(二)
    Android应用开发基础之三:数据存储和界面展现(三)
    Android应用开发基础之二:数据存储和界面展现(二)
    Android应用开发基础之一:数据存储和界面展现(一)
    Android之Fragment 基本介绍(转)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7251470.html
Copyright © 2011-2022 走看看