M.Wring Books
问从1到n所有数的数位加起来一共是多少
假设n为1025
我们分别从个位,十位,百位,...考虑
对于个位,1到1025每个数都有个位,所以加1025
对于十位,1到1025中1到9没有十位,所以加1025-9
对于百位,1到1025中1到99没有百位,所以加1025-99
对于千位,1到1025中1到999没有千位,所以加1025-999
AC代码:
#include
#include
#include
#include
#include
#include
#define endl '\n'
using namespace std;
typedef long long ll;
void solve(){
int x;
cin>>x;
string s=to_string(x);
int len=s.size()-1;
ll res=x;
int t=9;
for(int i=1;i<=len;i++){
res+=x-t;
t=t*10+9;
}
cout<>t;
while(t--)
solve();
return 0;
}
C.Beautiful Sequence
找到b[i]的最高位的1,由于b[i]=a[i]^a[i+1],又因为数组a非降序,所以a[i]的该位肯定是0(a[i]和a[i+1]的该位一位是0一位是1,又因为数组非降序)
然后根据将b[1],b[2],...b[i-1]全部异或起来,比如说
b[1],b[2],b[3],b[4],b[5]全部异或起来,然后中间a[2],a[3],a[3],a[4]都被抵消了,只剩下a[1]和a[5]的异或了,然后a[5]的某一位已经确定为0了,所以就能确定a[1]的这一位了
如果a[1]确定了,我们就能通过递推关系确定整个a序列,所以我们的任务就是确定a[1]
对于a[1]没有确定的位,我们就自己填充,具体解释见注释
AC代码:
#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int N=1e6+10;
int a[N],b[N];
int space[31];
int n,k;
//求x的最高位的1是第几位
inline int highbit(int x) {
//从2^30开始,即第31位开始,不断左移,如果遇到哪一位为1,就返回是第几位
for(int t=1<<30,cnt=31; t>0; t>>=1,cnt--) {
if(x&t) return cnt;
}
return -1;
}
void solve() {
memset(space,0,sizeof space);
cin>>n>>k;
for(int i=1; i>b[i];
for(int i=1; i0; j--) tmp^=b[j];
tmp&=i;
a[1]+=tmp;
}
//如果第cnt位的space值不等于0,说明第cnt位不能确定,那么就自己填充,确定的位我们已经改变不了了,然后未确定的位我们可以选择填充0还是1
//那么具体如何填充呢?因为我们要使得字典序是第k小的,所以我们未确定的位就和k(已经减过1了)的二进制对照,从最低位开始,第i次使用k(已经减过1了)的第i低的位进行填充
//pos表示二进制,pos不断左移,从1到10到100到1000...
else {
if(pos>k) continue;//如果已经填充为第k小的了,那么就不用继续填充了,前面补前导0就行了,而每一位本身就是0,所以根本无需操作,直接continue
if(k&pos) a[1]+=i;//如果k的这一位为1,那么就将a[1]的这一位改为1
pos<<=1;//pos左移一位
}
}
//pos由于最后多移动了一位,所以我们填充的其实少一位,这也就是为什么要取等号的原因,所以当pos小于等于k时,说明没有填充到第k小,输出-1
if(pos<=k) {
cout<<-1<>t;
while(t--)
solve();
return 0;
}
I.We love Strings
k>>1相当于k/2
k>>=1相当于k/=2
按字符串长度进行分类
当字符串长度小于等于20时,直接暴力枚举所有可能的字符串,放入set中,由于set会自动去重,所以只要返回set中的元素个数就行了
当字符串长度大于20时,对于长度为i的所有字符串,枚举所有选与不选这些字符串的二进制串,根据容斥原理算满足的个数(具体解释见注释)
证明见2023牛客暑假多校 C I M 题解 | JorbanS_JorbanS的博客-CSDN博客
容斥原理:
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int N=410,mod=998244353;
vectors[N];
setst;
string tmp;
int n;
void dfs(string s,int len,int cur) {
//s为当前已经生成的字符串
//cur表示当前填了几个了
if(s.size()==len) {
st.insert(s);
return;
}
//tmp是题目所给的字符串,s是我们自己构造的字符串,当前字符为?时,改成0或1,当前字符本来就为0或1时,那么直接就是原来的字符
if(tmp[cur]=='?') {
dfs(s+'1',len,cur+1);//始终搜长度为len的字符串
dfs(s+'0',len,cur+1);
} else {
dfs(s+tmp[cur],len,cur+1);
}
}
void solve() {
cin>>n;
for(int i=1; i<=n; i++) {
string ss;
cin>>ss;
int sz=ss.size();//字符串的长度
s[sz].push_back(ss);//长度相同的字符串都放在一个容器里
}
int ans=0;
//枚举字符串的长度
for(int i=1; i<=400; i++) {
if(!s[i].size()) continue;//如果没有长度为i的字符串,那么就continue
//如果字符串长度小于等于20
if(i<=20) {
for(auto ss:s[i]) {
tmp=ss;
dfs("",i,0);//从空字符串开始搜,搜所有长度为i的字符串
}
}
//如果字符串长度大于20
else {
int num=s[i].size();//长度为i的字符串有几个
int m=1<>t&1) {
cnt++;
//遍历长度为i的字符串s[i][t]中的每一个字符s[i][t][tt]
for(int tt=0; tt>t;
while(t--)
solve();
return 0;
}