【NOIP2013模拟联考12】数数(数位dp||类欧几里得)
来源:互联网 发布:发那科机器人编程软件 编辑:程序博客网 时间:2024/05/17 22:06
Description:
ztxz16从小立志成为码农,因此一直对数的二进制表示很感兴趣。今天的数学课上,ztxz16学习了等差数列的相关知识。我们知道,一个等差数列可以用三个数A,B,N表示成如下形式:
B + A, B + 2 * A, B + 3 * A, …, B + N * A
ztxz16想知道对于一个给定的等差数列,把其中每一项用二进制表示后,一共有多少位是1,但他的智商太低无法算出此题,因此寻求你的帮助。
1<=T<=20 , 1<=A<=10000 , 1<=B<=10^16 , 1<=N<=10^12
题解:
直觉告诉我这是个数位dp。
注意到a很小。
最接近a的2的幂是2^14。
把每个数的前14位和后面的位分开看。
前14位因为最多只有2^14个数,所以可以强行找循环节求答案。
对于后面的位,因为每次相当于加1个1或不加,产生的数是连续的,且加和不加也是个循环节,因此数位dp,只需要记录每个数mo循环节中1的个数的值即可算出贡献。
LL说这是个傻逼dp:
大概是直接以%a的值作为一个状态,求出b->b+a*n中%a=b%a的所有数的1的个数就好了。
呵呵。
题解的和infleaking的做法一致:按位搞贡献。
依次统计每一位上有多少1,对于第K位显然有:B+A与B+(2 ^ k + 1)A相同,因此可以将原等差数列拆分为若干循环节统计对于一个循环节内,可以将连续的一段0或者连续的一段1一起处理这样复杂度为 O(2^K/((2^K)/A)) = O(A)
高中一众大佬考场上类欧结果溢出成60points,只有gjx过,出题人被1ms怒艹。
之后去把类欧补充了下。
为了方便,先考虑b,最后把b减掉就行了。
枚举每一位k,单独算贡献。
这东西就是裸的类欧,后面的博客会详细介绍类欧的几种情况。
复杂度
注意之前提到的溢出。
类欧中间有一个n*(n+1)/2*(a/c)的计算。
n这么大,肯定GG。
所以可以开unsigned long long,相当于对2^64取模,因为最后的答案肯定小于2^64,所以这个方法是没问题的。
遇到n*(n+1)/2*(a/c)就判一下n是偶数还是奇数,先除以个2。
unsigned long long记得用%llu读入输出(cin,cout也没问题,突然想起了NOIP的痛~~)。
Code(类欧):
#include<cstdio>#define ul unsigned long long#define fo(i, x, y) for(int i = x; i <= y; i ++)using namespace std;ul T, a, b, n, ans, a2[65];ul f(ul a, ul b, ul c, ul n) { ul s = (n + 1) * (b / c); if(n % 2 == 0) s += n / 2 * (n + 1) * (a / c); else s += (n + 1) / 2 * n * (a / c); a %= c; b %= c; ul m = (a * n + b) / c; if(m == 0) return s; return s + n * m - f(c, c - b - 1, a, m - 1);}int main() { a2[0] = 1; fo(i, 1, 62) a2[i] = a2[i - 1] * 2; for(scanf("%llu", &T); T; T --) { scanf("%llu %llu %llu", &a, &b, &n); ans = 0; fo(k, 0, 60) if(b & a2[k]) ans --; fo(k, 0, 60) ans += f(a, b, a2[k], n) - f(a, b, a2[k + 1], n) * 2; printf("%llu\n", ans); }}
Code(分块+数位dp):
#include<cstdio>#include<cstring>#define ll long long#define fo(i, x, y) for(ll i = x; i <= y; i ++)#define fd(i, x, y) for(ll i = x; i >= y; i --)#define low(x) ((x) & -(x))using namespace std;ll T; ll st, ca, n, ans;const ll M = 1 << 14;ll a2[65];ll bz[M + 5], d[M + 5], jin[M + 5];ll sum(ll x) { ll s = 0; while(x) s ++, x -= low(x); return s;}void Find_xun() { memset(bz, 0, sizeof bz); d[0] = 0; ll x = st % M + ca; while(!bz[x % M]) { d[0] ++; jin[d[0]] = x / M; x %= M; bz[x] = 1; d[d[0]] = x; x += ca; }}void Tong_xiao() { fo(i, 1, d[0]) ans += sum(d[i]) * (n / d[0] + (n % d[0] >= i));}ll b[M + 5];ll f[65][M + 5][2], f1[65][M + 5][2], g[M + 5], g2[M + 5];void dp(ll n, ll m) { ll a[65]; a[0] = 0; while(n) a[++ a[0]] = n & 1, n >>= 1; memset(g, 0, sizeof g); if(a[0] == 0) return; memset(f, 0, sizeof f); memset(f1, 0, sizeof f1); f[a[0] + 1][0][1] = 1; fd(i, a[0], 1) { fo(j, 0, m - 1) { fo(k, 0, 1) if(f[i + 1][j][k]) { fo(p, 0, 1) { if(k && p > a[i]) continue; ll nj = (j + a2[i - 1] * p) % m; ll nk = k & (a[i] == p); f[i][nj][nk] += f[i + 1][j][k]; f1[i][nj][nk] += f1[i + 1][j][k] + p * f[i + 1][j][k]; } } } } fo(j, 0, m - 1) g[j] += f1[1][j][0] + f1[1][j][1];}void Tong_da() { if(n / d[0] < 2) { st /= M; fo(i, 1, n) { st += jin[(i - 1) % d[0] + 1]; ans += sum(st); } return; } ll ci = n / d[0], fi = 0, num = 0; fo(i, 1, d[0]) num += jin[i]; fo(i, 1, d[0]) if(jin[i]) { fi = i; break; } st /= M; dp(st, num); fo(i, 0, num - 1) g2[i] = g[i]; dp(st + (ci - 1) * num, num); fo(i, 0, num - 1) g[i] -= g2[i]; ans += sum(st) * (fi - 1); fo(i, fi, d[0]) st += jin[i], ans += g[st % num]; ans += g[st % num] * (fi - 1); n -= d[0] * (ci - 1) + (fi - 1); st += num * (ci - 2); ll nx = fi - 1; while(n) n --, nx = nx % d[0] + 1, st += jin[nx], ans += sum(st);}int main() { a2[0] = 1; fo(i, 1, 60) a2[i] = a2[i - 1] * 2; for(scanf("%lld", &T); T; T --) { scanf("%lld %lld %lld", &ca, &st, &n); Find_xun(); ans = 0; Tong_xiao(); Tong_da(); printf("%lld\n", ans); }}
- 【NOIP2013模拟联考12】数数(数位dp||类欧几里得)
- 3492. 【NOIP2013模拟联考12】数数(count)(循环节/DP)
- 【JZOJ 3492】【NOIP2013模拟联考12】数数(count)
- [jzoj]3468. 【NOIP2013模拟联考7】OSU!(osu) (期望DP)
- [jzoj]3472. 【NOIP2013模拟联考8】匹配(match)(AC自动机+DP)
- jzoj3501 【NOIP2013模拟联考15】消息传递(news) 树形dp
- 【NOIP2013模拟联考13】线段
- 【NOIP2013模拟联考7】数列
- 【NOIP2013模拟联考5】军训
- 【NOIP2013模拟联考6】选课
- 【NOIP2013模拟联考7】OSU
- 3486. 【NOIP2013模拟联考10】道路改建(rebuild)(2017.12A组)(tarjan缩环+拓补排序+DP+bitset)
- SSL2864 【NOIP2013模拟联考15】物语(spfa优化)
- 【NOIP2013模拟联考5】军训(training)
- 【NOIP2013模拟联考6】选课(select)
- 【NOIP2013模拟联考5】军训(training) 题解
- NOIP2013模拟联考5】军训(training)
- 【NOIP2013模拟联考2】摘取作物(pick)
- MacBook Pro 链接无线Wi-Fi网络问题(Wi-Fi正常打开,无法连接路由器)
- 吴恩达深度学习笔记之卷积神经网络(目标检测)
- visual studio编写C#代码时“未能从程序集.....中加载类型”和“找不到方法”的一种可能的解决办法
- 如何通过git将项目推送到github远程仓库
- 【Linux】查看ubuntu版本与位数
- 【NOIP2013模拟联考12】数数(数位dp||类欧几里得)
- Spark学习之SparkSession
- STM32单片机上位机程序代码(供参考)(基于C#开发)
- Ubuntu 下安装SublimeText Atom编辑器
- layer给iframe页面传值
- govendor使用笔记
- 实验(变位字谜 )
- icloud选择性备份iPhone7s的应用
- Bootstrap4(二十五)