Codeforces Round #723 (Div. 2) B. I Hate 1111

82 阅读2分钟

题目链接

codeforces.com/problemset/…

题意

给出n个数,判断每个数能否仅由11, 111, 1111 ……组合得到(可以选任意次)。

例如33 = 11 + 11 + 11, 144 = 111 + 11 + 11。所以33,144是可以的。

69 = 11 + 11 + 11 + 11 + 11 + 11 + 3, 显然69是不可以的

如果可以输出Yes,否则输出No。

思路

首先可以看出是一个完全背包的题目,通过预处理出所有由11,111,1111……能够组合出的所有的数,而考虑到数据范围为1x1091 \le x \le 10^9可以发现如果完全按照背包去写的话百分百会WA。

这里我们可以用到小凯的疑惑这里的结论

  • 设a,b为两个互质的数,a,b不能够组成的最大的数为ababa*b-a-b

显然11,111,1111….全部不要都是互质的数,因为111与1111能够组成的数那么11与111也可以组成,那么我们只需要选最小的11和111即可(具体证明过程可以去看看小凯的疑惑题解)

也就是说,1111111111=109911 * 111 - 11 - 111 = 1099,大于1099的所有数都是可以通过11,111的组合得到的。那么我们仅仅需要判断1~1099内所有能被11与111组合得到的数即可,这里可以通过完全背包预处理达到。

由于在这里的完全背包的预处理是常数级别,而且判断是O(1)O(1)的,所以此题的时间复杂度仅为O(t)O(t)

代码

#include <bits/stdc++.h>
#define up(i, j, n, k) for (int i = j; i <= n; i += k)
#define dw(i, j, n, k) for (int i = j; i >= n; i -= k)
#define LL long long

using namespace std;

typedef pair<int, int> PII;
const int mod = 998244353;
const int mn = 2e5 + 10;
const int INF = 0x3f3f3f3f;

int T;
int cnt, n;
int a[mn], b[mn];

void solve(){
	cin >> n;
    if (n > 1099) {
        cout << "Yes\n";
        return;
    }
    if (b[n]) 
        cout << "Yes\n";
    else 
        cout << "No\n";
}

int main() {
    T = 1;
    cin >> T;

    a[1] = 11, a[2] = 111;
    b[0] = 1;
    up(i, 1, 2, 1) 
        up(j, a[i], 1099, 1) 
            b[j] = max(b[j - a[i]], b[j]);

    while (T--) solve();
    return 0;
}