zoukankan      html  css  js  c++  java
  • 【题解】SCOI2010幸运数字

      最近在学习容斥相关,于是就看到了这个题。一开始以为是补集转化,但是观察一下马上发现不可行,好像直接做会比较容易一些。一个数满足要求的充要条件即为是一个幸运数字的倍数,那么容斥可以轻松搞定,只要枚举是一个数字/两个数字/三个数字的倍数……即可。打一个表找出<1e10的所有幸运数……竟然有2043个。不过显然其中互为倍数的那些个我们可以直接删掉其中大一些的那个数。这样删去之后,还剩下943个数。

      到这里我突然觉得好懵逼啊……左想右想再也想不出新的优化。于是看题解,发现竟然真的是爆搜加了两个剪枝。其中一个是当LCM>B的时候直接返回(不会产生贡献),第二个是从大到小排序,让大的数更容易被淘汰掉。果然爆搜的复杂度是非常玄妙的一件事……竟然跑得飞快?启发是一定要勇敢的打暴力,没准就过了(・ω <)

      不过为什么只有我一个要开unsigned long long 捏……

    #include <bits/stdc++.h>
    using namespace std;
    #define int unsigned long long
    #define ll long long
    #define maxn 5000
    int A, B, ans, luck[maxn], data[maxn];
    int tot, cnt;
    
    int read()
    {
        int x = 0, k = 1;
        char c;
        c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    void dfs(int now, int n)
    {
        if(now) luck[++ cnt] = now;
        if(now * (ll) 10 + (ll) 6 <= n) dfs(now * (ll) 10 + (ll) 6, n);
        if(now * (ll) 10 + (ll) 8 <= n) dfs(now * (ll) 10 + (ll) 8, n);
    }
    
    bool cmp(int a, int b) { return a > b; }
    
    int GCD(int a, int b)
    {
        while(b)
        {
            int c = a % b;
            a = b;
            b = c;
        }
        return a;
    }
    
    void solve(int num, int cnt, int lcm)
    {
         if(num > tot)
        {
            if(cnt)
            {
                if(cnt & 1) ans += (B / lcm) - ((A - 1) / lcm);
                else ans -= (B / lcm) - ((A - 1) / lcm);
            }
            return;
        }
        solve(num + 1, cnt, lcm);
        int gcd = GCD(data[num], lcm);
        int LCM = (lcm / gcd) * data[num];
        if(LCM <= B) solve(num + 1, cnt + 1, LCM);
    }
    
    
    signed main()
    {
        A = read(), B = read();
        dfs(0, B);
        sort(luck + 1, luck + 1 + cnt);
        for(int i = 1; i <= cnt; i ++)
        {
            data[++ tot] = luck[i];
            for(int j = 1; j < tot; j ++)
                if(!(luck[i] % data[j])) { tot --; break; }
        }
        sort(data + 1, data + 1 + tot, cmp);
        solve(1, 0, 1);
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    转贴ARM NEON 优化的例子
    GP(General-purpose Processor)与DSP的存储器结构区别
    arm中的饱和指令
    MIPS,MCPS, MHz for voice codec
    免费提供万方论文
    ARM CORTEX Ax NEON 中的加法指令
    android C编程技巧 及 C/C++开发测试(转)
    SQL Server 存储过程的经典分页 GO
    详细设计说明书大纲 GO
    正则表达式介绍 GO
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9032897.html
Copyright © 2011-2022 走看看