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. Oracle中varchar2(XX)和varchar2(XX byte)区别

    这两个相不相同是由参数NLS_LENGTH_SEMANTICS决定的,有两个单位,char(字符)或者字节(byte),该参数默认值为BYTE. alter session set nls_lengt ...

  2. [问题解决]同时显示多个Notification时PendingIntent的Intent被覆盖?

    情况是这样的,使用NotificationManager触发多个Notification: private Notification genreNotification(Context context ...

  3. Scrapy:创建爬虫程序的方式

    Windows 10家庭中文版,Python 3.6.4,Scrapy 1.5.0, 在Scrapy中,建立爬虫程序或项目的方式有两种(在孤读过Scrapy的大部分文档后): 1.继承官方Spider ...

  4. Windows 10安装uWSGI:不可行、失败了

    Windows 10家庭中文版,Python 3.6.4,uwsgi-2.0.17.tar.gz,压缩工具-7-zip 提示:请不要和我一样尝试,浪费时间,去Linux上玩吧! 几个小时的安装经历 昨 ...

  5. 数据库-mysql函数

    一:MySQL中提供了许多内置函数 CHAR_LENGTH(str) 返回值为字符串str 的长度,长度的单位为字符.一个多字节字符算作一个单字符. 对于一个包含五个二字节字符集, LENGTH()返 ...

  6. URL的井号

    2010年9月,twitter改版. 一个显著变化,就是URL加入了"#!"符号.比如,改版前的用户主页网址为 http://twitter.com/username 改版后,就变 ...

  7. linux java配置

    1.java配置 配置环境变量在/etc/profile下增加# set Java environmentJAVA_HOME=/usr/share/jdk1.6.0_43PATH=$JAVA_HOME ...

  8. wpf listBox的item,滚动条拖到低部,底部内容不能完全显示的问题

    listBox外部包裹一层 <ScrollViewer VerticalScrollBarVisibility="Auto"> 然后修改listBox的style,取消 ...

  9. C压缩字符串中的空格

    使用纯C语言,去除一个字符串开头和结尾的空格,内部若有连续空格只保留一个.  C Code  12345678910111213141516171819202122232425262728293031 ...

  10. Elasticsearch: 权威指南---基础入门

    1.查看方式:GETURL:http://10.10.6.225:9200/?pretty pretty 在任意的查询字符串中增加pretty参数.会让Elasticsearch美化输出JSON结果以 ...