题目链接
题意
给出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……能够组合出的所有的数,而考虑到数据范围为可以发现如果完全按照背包去写的话百分百会WA。
这里我们可以用到小凯的疑惑这里的结论
- 设a,b为两个互质的数,a,b不能够组成的最大的数为。
显然11,111,1111….全部不要都是互质的数,因为111与1111能够组成的数那么11与111也可以组成,那么我们只需要选最小的11和111即可(具体证明过程可以去看看小凯的疑惑题解)
也就是说,,大于1099的所有数都是可以通过11,111的组合得到的。那么我们仅仅需要判断1~1099内所有能被11与111组合得到的数即可,这里可以通过完全背包预处理达到。
由于在这里的完全背包的预处理是常数级别,而且判断是的,所以此题的时间复杂度仅为。
代码
#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;
}