【10.17校内测试】【二进制数位DP】【博弈论/预处理】【玄学(?)DP】
Solution
几乎是秒想到的水题叻!
异或很容易想到每一位单独做贡献,所以我们需要统计的是区间内每一位上做的贡献,就是统计区间内每一位是1的数的数量。
所以就写数位dp辣!(昨天才做了数字统计不要太作弊啊!)
Code
- #include<bits/stdc++.h>
- #define LL long long
- #define mod 1000000007
- using namespace std;
- inline void read(LL &x) {
- x = ; char ch = getchar();
- while(ch > '' || ch < '') ch = getchar();
- while(ch >= '' && ch <= '') {
- x = x * + ch - '';
- ch = getchar();
- }
- }
- int num[];
- LL L, R, dp[][][];
- LL dfs(int dep, int up, int is, int idc) {
- if(!dep && is) return ;
- if(!dep) return ;
- if(~dp[dep][up][is]) return dp[dep][up][is];
- int h = up ? num[dep] : ;
- LL tmp = ;
- for(int i = ; i <= h; i ++) {
- if(dep == idc && i == ) tmp += dfs(dep - , up && i == h, , idc);
- else tmp += dfs(dep - , up && i == h, is, idc);
- }
- return dp[dep][up][is] = tmp;
- }
- LL sov(int x, int idc) {
- memset(dp, -, sizeof(dp));
- memset(num, , sizeof(num));
- int tot = ;
- while(x) {
- num[++ tot] = x % ;
- x /= ;
- }
- return dfs(tot, , , idc);
- }
- void work() {
- int t = R, dep = ;
- LL ans = ;
- while(t) {
- dep ++;
- LL t1 = sov(R, dep);
- LL t2 = L ? sov(L - , dep) : ;
- LL num1 = t1 - t2;
- ans = (ans + * num1 % mod * (R - L + - num1) % mod * ( << dep - ) % mod) % mod;
- t >>= ;
- }
- printf("%lld\n", ans);
- }
- int main() {
- freopen("xor.in", "r", stdin);
- freopen("xor.out", "w", stdout);
- int T;
- scanf("%d", &T);
- while(T --) {
- read(L); read(R);
- work();
- }
- return ;
- }
Solution
博弈论什么的完全不了解啊....然后看到题就乱打了个记忆化搜索,结果就70pts!!
原来这样暴力是$n^4$的复杂度啊...运气太好了...
只有两堆石子的做法:
大名鼎鼎的威佐夫博弈
通过一个简单的搜索,不难发现它的必败状态为:
$(1, 2), (3, 5), (4, 7), (6, 10), (8, 13)$……
通过这个表,能发现什么规律?
每个自然数出现一次
相邻两个必败态中,石子个数之差恰好增加 1
这样两个现象其实是非常合理的:
给定$x$,应该只存在一个$y$使得 $(x, y)$ 是先手必败态
所有不同的先手必败态的 $(y-x)$ 应该互不相同
它们都来源于同一个事实:先手必败状态无法转移到另一个先手必败状态。
一般做法:
我们考虑优化之前的筛法
根据上一页的思路,不难想到,给定 $x, y$ 之后,使得$(x, y, z)$ 为先手必败态的$z$只有一个
不妨用$f(x, y)$ 表示这个$z$
我们从小到大枚举一个变量$i$,然后计算:
有多少个$f(x, y)$ 的值为$i$
如果我们从小到大枚举 i,枚举到当前的 i 时:
所有$f(x, y)<i$的状态已经计算完毕,若一个$f(x, y)=k<i$,那么代表着$f(x+k, y), f(x, y + k), f(x+k,y+k) 均不可能是$i$
所有$f(x, y)=i$的状态中,每个自然数出现不超过 1 次,且$|x-y|$ 应该互不相同
根据这三个原则,我们可以在$O(n^2)$的枚举中,发现所有$f(x, y)=i$的状态$(x,y)$。
然而并不是很懂题解....然后$yuli$dalao讲解了另一种更好理解的方法!
当确定了一个数时,如果另外两个数的差相同,那么就可以一步转化。
同理,确定了两个数,另一个数多少也可以一步转化。
确定了三个数大小之间的差,也可以一步转化。
以上7种情况,如果按顺序从小到大枚举三个数,如果出现上述情况中存在必败态,那么当前状态可以必胜。
预处理$n^3$即可。
Code
标程
- #include <bits/stdc++.h>
- #define rep(i, x, y) for (int i = (x), _ = (y); i < _; ++i)
- #define down(i, x, y) for (int i = (x) - 1, _ = (y); i >= _; --i)
- #define fi first
- #define se second
- #define mp(x, y) make_pair(x, y)
- #define pb(x) push_back(x)
- #define bin(x) (1 << (x))
- #define SZ(x) int((x).size())
- //#define LX_JUDGE
- using namespace std;
- typedef pair<int, int> pii;
- typedef vector<int> Vi;
- typedef long long ll;
- template<typename T> inline bool upmax(T &x, T y) { return x < y ? (x = y, ) : ; }
- template<typename T> inline bool upmin(T &x, T y) { return x > y ? (x = y, ) : ; }
- namespace MATH_CAL {
- const int mod = 1e9 + ;
- inline int add(int a, int b) { return a + b >= mod ? a + b - mod : a + b; }
- inline int sub(int a, int b) { return a - b < ? a - b + mod : a - b; }
- inline int mul(int a, int b) { return (ll) a * b % mod; }
- inline void Add(int &a, int b) { (a += b) >= mod ? a -= mod : ; }
- inline int qpow(int x, int n) { int r = ; for ( ; n; n /= , x = mul(x, x)) if (n & ) r = mul(r, x); return r; }
- inline int mod_inv(int x) { return qpow(x, mod - ); }
- } using namespace MATH_CAL;
- const int MAX_N = ;
- int f[MAX_N][MAX_N], now[MAX_N][MAX_N];
- int dif[MAX_N], vlef[MAX_N], tim;
- int main() {
- #ifdef LX_JUDGE
- freopen(".in", "r", stdin);
- #endif
- freopen("stone.in", "r", stdin);
- freopen("stone.out", "w", stdout);
- int N = ;
- rep (i, , N) memset(f[i], 0x3f, sizeof(int) * N);
- for (int i = ; i < N; ++i) {
- ++tim;
- for (int j = ; j < N; ++j) {
- for (int k = ; k <= j; ++k) {
- if (f[j][k] < i) {
- int v = i - f[j][k];
- if (j + v < N) now[j + v][k] = tim;
- if (k + v < N) now[j][k + v] = tim;
- if (max(j, k) + v < N) now[j + v][k + v] = tim;
- } else if (max(now[j][k], now[k][j]) < tim and max(dif[abs(j - k)], max(vlef[j], vlef[k])) < tim) {
- f[k][j] = f[j][k] = i;
- dif[abs(j - k)] = tim;
- vlef[j] = tim;
- vlef[k] = tim;
- }
- }
- }
- }
- int T;
- scanf("%d", &T);
- while (T--) {
- int x, y, z;
- scanf("%d%d%d", &x, &y, &z);
- puts(f[x][y] == z ? "No" : "Yes");
- }
- return ;
- }
- /*
- f_0[i][j] is easy to compute
- f_1[i][j] = !(f_0[i - 1][j] or f_0[i][j - 1] or f_0[i - 1][j - 1] or f_1[i - k][j - k])
- Let
- S1 = { f[i - k][j - k], f[i - k][j], f[i][j - k] };
- S2 = { f[i - k][j - k] + k, f[i - k][j] + k, f[i][j - k] + k };
- f[i][j] = mex { S1, S2 }
- */
第二解
- #include<bits/stdc++.h>
- #define RG register
- using namespace std;
- int SG[][][];
- inline void read(int &x) {
- x = ; char ch = getchar();
- while(ch > '' || ch < '') ch = getchar();
- while(ch >= '' && ch <= '') {
- x = x * + ch - '';
- ch = getchar();
- }
- }
- int QAQ[][][], f[][][];
- void work() {
- for(int i = ; i <= ; i ++)
- for(int j = ; j <= i; j ++)
- for(int k = ; k <= j; k ++) {
- int pd = ;
- if(QAQ[i][j - k][]) pd = ;
- if(QAQ[j][i - k][]) pd = ;
- if(QAQ[k][i - j][]) pd = ;
- if(QAQ[i][j][]) pd = ;
- if(QAQ[i][k][]) pd = ;
- if(QAQ[j][k][]) pd = ;
- if(QAQ[i - j][j - k][]) pd = ;
- if(pd) {
- f[i][j][k] = ;
- QAQ[i][j - k][] = QAQ[j][i - k][] = QAQ[k][i - j][] = QAQ[i][j][] = QAQ[j][k][] = QAQ[i][k][] = QAQ[i - j][j - k][] = ;
- }
- }
- }
- int main() {
- freopen("stone.in", "r", stdin);
- freopen("stone.out", "w", stdout);
- int T;
- scanf("%d", &T);
- work();
- while(T --) {
- int q[];
- read(q[]); read(q[]); read(q[]);
- sort(q, q + );
- if(!f[q[]][q[]][q[]]) printf("Yes\n");
- else printf("No\n");
- }
- return ;
- }
Solution
完全不想写题解....
七高欢乐全场爆零题~
Code
- #include<bits/stdc++.h>
- using namespace std;
- int n, k, a[];
- int f[][][];
- int main() {
- freopen("optimization.in", "r", stdin);
- freopen("optimization.out", "w", stdout);
- scanf("%d%d", &n, &k);
- for(int i = ; i <= n; i ++) scanf("%d", &a[i]);
- memset(f, -0x3f3f3f3f, sizeof(f));
- for(int i = ; i <= n; i ++) f[i][][] = f[i][][] = ;
- for(int i = ; i <= n; i ++)
- for(int j = ; j <= k; j ++) {
- int flag = - (j == || j == k);
- f[i][j][] = max(f[i - ][j][], max(f[i - ][j - ][], f[i - ][j - ][])) + flag * a[i];
- f[i][j][] = max(f[i - ][j][], f[i - ][j - ][]);
- f[i][j][] = max(f[i - ][j][], max(f[i - ][j - ][], f[i - ][j - ][])) - flag * a[i];
- f[i][j][] = max(f[i - ][j][], f[i - ][j - ][]);
- if(j > ) {
- f[i][j][] = max(f[i - ][j - ][], f[i][j][]);
- f[i][j][] = max(f[i - ][j - ][], f[i][j][]);
- }
- }
- int ans = -1e9;
- for(int i = k; i <= n; i ++)
- ans = max(ans, max(f[i][k][], f[i][k][]));
- printf("%d", ans);
- return ;
- }
【10.17校内测试】【二进制数位DP】【博弈论/预处理】【玄学(?)DP】的更多相关文章
- 【10.29校内测试】【线段树】【DP】【二进制Trie树求最小值最大】
Solution 标程太暴力惹QAQ 相当于是26棵线段树的说QAQ 不过我写了另一种写法,从大到小枚举每一个字母,标记字典序在这个字母之上的位置为1,每次都建一棵线段树,维护1的数量,即区间和. 修 ...
- 【10.26校内测试】【状压?DP】【最小生成树?搜索?】
Solution 据说正解DP30行??? 然后写了100行的状压DP?? 疯狂特判,一算极限时间复杂度过不了aaa!! 然而还是过了....QAQ 所以我定的状态是待转移的位置的前三位,用6位二进制 ...
- 【10.5校内测试】【DP】【概率】
转移都很明显的一道DP题.按照不优化的思路,定义状态$dp[i][j][0/1]$表示吃到第$i$天,当前胃容量为$j$,前一天吃(1)或不吃(0)时能够得到的最大价值. 因为有一个两天不吃可以复原容 ...
- 【10.4校内测试】【轮廓线DP】【中国剩余定理】【Trie树+博弈】
考场上几乎是一看就看出来轮廓线叻...可是调了两个小时打死也过不了手出样例!std发下来一对,特判对的啊,转移对的啊,$dp$数组竟然没有取max!!! 某位考生当场死亡. 结果下午又请了诸位dala ...
- 【8.17校内测试】【模拟】【set】【网络流】
为什么每次想的最久的题得的分数最低!!!qwqwq 再也不在noip上尝试A*叻!! 模拟题,先把能消的消掉,双指针从两端向中间扫描,如果头尾合并可以消,就把它消掉,最后判断一下.因为消完过后num保 ...
- 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】
Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...
- 【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】
最开始想的暴力DP是把天数作为一个维度所以怎么都没有办法优化,矩阵快速幂也是$O(n^3)$会爆炸. 但是没有想到另一个转移方程:定义$f[i][j]$表示每天都有值的$i$天,共消费出总值$j$的方 ...
- 【10.11校内测试】【优先队列(反悔贪心)】【莫队】【stl的应用??离线处理+二分】
上次做过类似的题,原来这道还要简单些?? 上次那道题是每天可以同时买进卖出,所以用两个优先队列,一个存买进,一个存卖出(供反悔的队列). 这道题实际上用一个就够了???但是不好理解!! 所以我还是用了 ...
- 2018.10.17校内模拟赛:T2神光
题面:pdf 首先排序,二分,然后怎么判定是否可行. 最简单的思路是,dp[i][j][k],到第i个,用了j次红光,k次绿光,前i个点都选上了,是否可行.然后转移就行. 然后考试的时候就想到这了,往 ...
随机推荐
- MFC将二进制文件导入资源后释放
1.前言 前一篇笔记记录了怎么修改PE,此篇记录下如何利用自身的资源文件. 2.编程思路 获得资源句柄 - 获得资源文件大小 - 加载资源文件 - 锁定资源并获得其指针. 3.实践代码 1)编译以下代 ...
- 渗透测试===使用BURPSUIT暴力破解某网站的手机验证码
手机短信验证是企业给消费者(用户)的一个凭证,通过手机短信内容的验证码来验证身份.主要用来用户注册,找回密码,用户登录等等作为强身份认证. 目前验证码的格式主要是数字,从4位到6位不等.一般来说验 ...
- dorado 的学习位置、控件使用方法查找、示例演示地址
dorado的学习位置: http://wiki.bsdn.org/display/dorado7/Project+Home dorado的控件使用方法查找: http://dorado7.bsdn. ...
- Django 内置模板标签和过滤器
一.内置模板标签 语法:{% %} autoescape : 是否转义,on或off作为参数,并确定自动转义是否在块内有效.该块以endautoescape结束 {% autoescape on % ...
- ios 个人开发者账户 给其他团队用坑爹的教程
最新版本的 ios 支持 3个开发者证书 和 3个发布者证书 ,如果是多余3台电脑设备要真机调试,就比较麻烦 (手机支持100个设备) 解决方案就是: 在别人的电脑上要成功安装,须具备两个文件: ...
- Flask:初见
Windows 10家庭中文版,Python 3.6.4 从Flask官网开始学起. 介绍 Flask是一个Python的Web开发微框架,基于Werkzeug.Jinja2模块(and good i ...
- thinkphp5高亮当前页(仅针对个人项目记录,不做通用参考)
<div class="navbg"> <ul class="menu"> <li> <a href="/& ...
- https页面打不开
https://blog.csdn.net/leedaning/article/details/71552625
- 2588: Count on a tree
敢问和zwt的树有何区别..改了读入直接交..四百个人A,三百多个PE..于是果断贡献几发PE.. http://ideone.com/9XCg3D
- Rookey.Frame之系统初始化
昨天介绍了数据库的配置,今天继续介绍系统的初始化功能:针对系统初始化在开发中也是很重要的一部分,它可以提前将相关数据提前自动初始化到系统中,同时也可以为上线测试提供方便,可以很方便进行系统测试演练,防 ...