B. I Hate 1111
题目大意
给你一个数问你是否可以由11,111,…11111…组合而成
思路
不难看出11和111可以组成所有的1的数,那么回到最朴素的罪罚就是你每次枚举111的系数然后x减去
111
∗
系
数
111*系数
111∗系数然后判断这个差能否模11为0。
第二种方法就是
你先将x除以11得到的商a,x模11得到的余b,那么如果余不为0是不是可以将其转化成111,那么这里就需要要求商需要大于等于10,才能化成111你余数是多少那么你要转换成的111就是多少,就是你需要多少个商里的10,那么判断条件就是
b
∗
10
b*10
b∗10
⩽
\leqslant
⩽
a
a
a你可看出当x大于一定值的时候是一定可以组合出来的
第三种方法就完全背包了。枚举状态维护最大值。
朴素code
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
std::cin>>t;
while(t--){
int x;
std::cin>>x;
bool flag = false;
for(int i=0;i*111<=x;i++){
if((x-i*111)%11==0){
flag = true;
break;
}
}
if(flag)puts("YES");
else puts("NO");
}
return 0;
}
O(1)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
int t;
std::cin>>t;
while(t--){
ll x;
std::cin>>x;
int q=x/11;
int p=x%11;
if(q>=p*10)puts("YES");
else puts("NO");
}
return 0;
}
完全背包
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int v[3] = {0,11,111};
int f[N];
int main(){
int t;
std::cin>>t;
while(t--){
int x;
std::cin>>x;
if(x>2000){puts("YES"); continue;}
memset(f,0,sizeof(f));
for(int i = 1; i <= 2; i++){
for(int j = v[i]; j <= x; j++){
f[j] = max(f[j], f[j-v[i]]+v[i]);
}
}
if(f[x]==x)puts("YES");
else puts("NO");
}
return 0;
}