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】的更多相关文章

  1. 【10.29校内测试】【线段树】【DP】【二进制Trie树求最小值最大】

    Solution 标程太暴力惹QAQ 相当于是26棵线段树的说QAQ 不过我写了另一种写法,从大到小枚举每一个字母,标记字典序在这个字母之上的位置为1,每次都建一棵线段树,维护1的数量,即区间和. 修 ...

  2. 【10.26校内测试】【状压?DP】【最小生成树?搜索?】

    Solution 据说正解DP30行??? 然后写了100行的状压DP?? 疯狂特判,一算极限时间复杂度过不了aaa!! 然而还是过了....QAQ 所以我定的状态是待转移的位置的前三位,用6位二进制 ...

  3. 【10.5校内测试】【DP】【概率】

    转移都很明显的一道DP题.按照不优化的思路,定义状态$dp[i][j][0/1]$表示吃到第$i$天,当前胃容量为$j$,前一天吃(1)或不吃(0)时能够得到的最大价值. 因为有一个两天不吃可以复原容 ...

  4. 【10.4校内测试】【轮廓线DP】【中国剩余定理】【Trie树+博弈】

    考场上几乎是一看就看出来轮廓线叻...可是调了两个小时打死也过不了手出样例!std发下来一对,特判对的啊,转移对的啊,$dp$数组竟然没有取max!!! 某位考生当场死亡. 结果下午又请了诸位dala ...

  5. 【8.17校内测试】【模拟】【set】【网络流】

    为什么每次想的最久的题得的分数最低!!!qwqwq 再也不在noip上尝试A*叻!! 模拟题,先把能消的消掉,双指针从两端向中间扫描,如果头尾合并可以消,就把它消掉,最后判断一下.因为消完过后num保 ...

  6. 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

    Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...

  7. 【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】

    最开始想的暴力DP是把天数作为一个维度所以怎么都没有办法优化,矩阵快速幂也是$O(n^3)$会爆炸. 但是没有想到另一个转移方程:定义$f[i][j]$表示每天都有值的$i$天,共消费出总值$j$的方 ...

  8. 【10.11校内测试】【优先队列(反悔贪心)】【莫队】【stl的应用??离线处理+二分】

    上次做过类似的题,原来这道还要简单些?? 上次那道题是每天可以同时买进卖出,所以用两个优先队列,一个存买进,一个存卖出(供反悔的队列). 这道题实际上用一个就够了???但是不好理解!! 所以我还是用了 ...

  9. 2018.10.17校内模拟赛:T2神光

    题面:pdf 首先排序,二分,然后怎么判定是否可行. 最简单的思路是,dp[i][j][k],到第i个,用了j次红光,k次绿光,前i个点都选上了,是否可行.然后转移就行. 然后考试的时候就想到这了,往 ...

随机推荐

  1. python pachong zhuanzai

    come from:http://www.cnblogs.com/dyllove98/archive/2013/07/12/3187186.html 先来说一下我们学校的网站: http://jwxt ...

  2. 编写shell脚本一键启动zookeeper集群!!

    踩了一个多小时坑终于解决了: 这里分享给大家,更主要的目的是记住这些坑,避免以后重复走!!! 首先,这里采用ssh秘钥方式进行集群主机之间免密登录执行启动命令 这里简单说下原理: 通过ssh去另外一台 ...

  3. Python-Web框架的本质

    Web框架的本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. Python中使用socket和 ...

  4. mysql慢sql报警系统

    前言:最近有同事反应有的接口响应时间时快时慢,经过排查有的数据层响应时间过长,为了加快定位定位慢sql的准确性,决定简单地搭建一个慢sql报警系统 具体流程如下架构图 第一步:记录日志 每个业务系统都 ...

  5. SQL2000数据库修改sa密码

    开始——程序——Microsoft SQL Server——企业管理器 2 展开数据库Microsoft SQL Server—— SQL Server组——安全性——登录——双击sa 3 在常规内有 ...

  6. Linux密码策略-密码长度-密码复杂度

    1.设置密码长度 vim /etc/pam.d/system-authpassword requisite pam_cracklib.so try_first_pass retry=3 minlen= ...

  7. 30 最小的k个数

    输入n个整数,找出其最小的k个数,例如输入4,5,1,6,2,7,3,8,最小的4个数为1,2,3,4 解法一:快排思想,会改变原数组    O(n) 注意是vector<int>& ...

  8. MySQL下concat函数中null值问题

    在mysql中,使用CONCAT(str1,str2,...)函数拼接字符串的过程中,如果你拼接的字段当中有值为null,那么拼接的结果就为null 注: select CONCAT(字段1,字段2) ...

  9. loadrunner——常见函数

    loadrunner——常见函数 分类: LoadRunner 2012-04-11 20:41 703人阅读 评论(0) 收藏 举报 loadrunnersearchweb服务器脚本stringwe ...

  10. Django实战(22):处理登录和注销

    我们已经可以在view函数中判断用户是否已经登录以及获取用户信息: if request.user.is_authenticated(): #判断用户是否已登录 user = request.user ...