题意给你两个数l,m,大小为m的数组a,求[0,l]之间满足以下条件的数x的个数:对于任何i输入[0,m-1],f(x+i)%2=a[i];f(k):代表k在二进制下1的个数m的范围<=100,l<=1e18,a[i] = 0/1
思路显然l的范围1e18,大概率就是数位DP了
- 观察到m是<=100的,因此x+m只会改变后7位置 , 对于前面的位数 , 则只会进1,使得前面连续的0变成1;
- 那么只要对前半部分进行数位DP,dp[pos][lim][cnt][d]代表位置在pos处,lim代表有无达到上限,cnt为1代表前面有奇数个1为0代表偶数个1,d代表从pos起向前有偶数还是奇数个1;
- 对于第七位以后的部分,直接暴力计算就好了,统计以下是否进位;
#include <bits/stdc++.h>using namespace std;#define nl "\n"#define nf endl#define ll long long#define pb push_back#define _ << ' ' <<#define INF (ll)1e18#define mod 998244353#define maxn 110#define lc 1338557220ll i, i1, j, k, k1, t, n, m, res, flag[10], a, b;ll x, rs[maxn], p;vector<ll> pw = {23, 19, 17, 13, 11, 9, 7, 5, 4};ll ask(ll a, ll b) {cout << "?" _ a _ b << nf;ll x;cin >> x;return x;}void clm(ll x) {cout << "!" _ x << nf;}int main() {ios::sync_with_stdio(0);cin.tie(0);/* #if !ONLINE_JUDGE && !EVALifstream cin("input.txt");ofstream cout("output.txt");#endif */// kudos for automatic wacin >> t;while (t--) {for (i = 1; i <= 23; i++) {k = ask(x + i, lc + i);for (j = 0; j < 9; j++) {if (k % pw[j] == 0) rs[j] = (-i % pw[j] + pw[j]) % pw[j];}}k = 1;p = 1;for (j = 0; j < 9; j++) {// cout << "p =" _ p << nf;while (p % pw[j] != rs[j]) p += k;k *= pw[j];}clm(p);}return 0;}
【ICPC 第 45 届国际大学生程序设计竞赛亚洲区域赛(济南)-L Bit Sequence】
推荐阅读
- 十大奢侈品牌围巾 阿玛尼仅第七,第一是上层社会的宠儿
- 三国梗传第39关吕布战曹操怎么通关
- 剑与远征8月诗社竞答第六天答案是什么
- 轻功是怎样练成的(世界轻功第一人)
- 赛尔号谱尼第二道封印怎么打(赛尔号谱尼被封印)
- 赛尔号谱尼超进化第五关光明之愿怎么打(赛尔号谱尼超进化第五封印怎么打)
- 魔镜物语命运棋局第五章怎么通关
- 原神掠影拾真第二天拍照位置在哪
- DTSE Tech Talk | 第9期:EiPaaS驱动企业数字化转型
- 梦幻西游手游金石之域第十二关怎么通关