【数位dp?】CodeForces 288E Polo the Penguin and Lucky Numbers
2015-03-27 17:12
459 查看
题目点这里
那么好吧终于把这道题折腾完了
以及我并不觉得这是dp = =
题意:所有数位仅含4和7的数为lucky number 设[L, R]中第i大的lucky number为ai 求 a1*a2 + a2*a3 + a3*a4 +... an-1*an
L和R的范围是10的10000次方 好吧 这数据范围就是数位dp的标准范围了 = =(不!其实一般的数位dp根本没这么变态!)
然后就想要怎么维护这个相邻两项乘积的和……嗯…………好像和平方减去平方和有点像…………展开一看……好像不太对QAQ……
然后我去问了鲲哥 小明 翔爷 = =嗯……都没想法………………
于是去看了官方题解……maya英文渣跪了…………
= =然后看ac code。。。maya这些预处理都是在搞什么鬼…………= =
感觉喵生没有希望了。
然后lhy同学。。看了那些代码 = =十分神奇地写出了一个公式
然后拆拆拆。。。推推推………………居然就…………推出来了………………
orz让我跪跪
orz其实根本不需要预处理
orz其实递推就可以了。。
让我来整理一下思路。。。(反正也不是我想出来的T_T)
首先 和大部分(不是所有)的数位dp一样 这个答案是可以相减的
也就是说 可以分开处理L和R再相减就可以了
但是这里的答案是solve(R) - solve(L)而不是L - 1 因为上界an * an+1是不算在答案里的而下界a1 * a2是算在答案里的
假设我们现在要求的是solve(X) 认为比X小的并且与X位数相等的幸运数字都是合法的(注意L和R位数是一样的)
把X的前n位取出来看成一个数C(比如说 X = 477444 i = 3时 C = 477)设Fn表示solve(C) Kn表示比C小与C位数相等的幸运数字个数。由定义 有:
如果已知Fi 那么 当X[n + 1] == 4时 有:
当X[n + 1] == 7时 有:
其实差别只在第一个sigma的上标 那么先考虑X[n + 1] == 4的情况:
将之前的定义式带入得:
然后可以发现:
那么带上去得:
然后。。。我们维护一个ai的和和一个ai^2的和再记录akn和a1还有kn 就可以递推了……
关于怎么维护……暴力拆一下 = =
然后……当X[i + 1] == 7的时候 我们把最后多出来的(10*ak+4)(10*ak+7)算上就行了。注意 ai == 10*ak+4而不是10*ak+7
因为我怕爆 long long 又觉得中途取模不好看。。所以用的是 unsigned long long = =但是乘的时候还是爆了T_T。。。。所以中途还是取了模。。。。。
那么其实代码一共只有39行。。但是它背后却是上面一堆乱七八糟丧心病狂非人哉的公式…………
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
typedef unsigned long long ULL;
const int Mod = 1000000007;
ULL solve()
{
string s; cin >> s; int len = s.size();
ULL F = 0llu, suq = 0llu, sum = 0llu, ak = 0llu, a1 = 0llu, K = 1llu;
for(int i = 0; i < len; ++i)
{
F = 100 * F + 100 * suq + 220 * sum + 70 * (ak + Mod - a1) % Mod + 56 * (K - 1); F %= Mod;
suq = 200 * suq + 220 * sum + 65 * (K - 1); suq %= Mod;
sum = 20 * sum + 11 * (K - 1); sum %= Mod;
if(s[i] ^ '4')
{
F += ((ak * 10 + 4) % Mod) * ((ak * 10 + 7) % Mod); F %= Mod;
suq += ((ak * 10 + 4) % Mod) * ((ak * 10 + 4) % Mod); suq %= Mod;
sum += ak * 10 + 4; sum %= Mod;
}
ak = ak * 10 + s[i] - '0'; ak %= Mod; a1 = a1 * 10 + 4; a1 %= Mod;
K = (K - 1) * 2; K += (s[i] == '4') ? 1 : 2; K %= Mod;
}
return F;
}
int main()
{
ios :: sync_with_stdio(false);
ULL res = -solve(); res += solve();
cout << (res + Mod) % Mod << endl;
return 0;
}
那么好吧终于把这道题折腾完了
以及我并不觉得这是dp = =
题意:所有数位仅含4和7的数为lucky number 设[L, R]中第i大的lucky number为ai 求 a1*a2 + a2*a3 + a3*a4 +... an-1*an
L和R的范围是10的10000次方 好吧 这数据范围就是数位dp的标准范围了 = =(不!其实一般的数位dp根本没这么变态!)
然后就想要怎么维护这个相邻两项乘积的和……嗯…………好像和平方减去平方和有点像…………展开一看……好像不太对QAQ……
然后我去问了鲲哥 小明 翔爷 = =嗯……都没想法………………
于是去看了官方题解……maya英文渣跪了…………
= =然后看ac code。。。maya这些预处理都是在搞什么鬼…………= =
感觉喵生没有希望了。
然后lhy同学。。看了那些代码 = =十分神奇地写出了一个公式
然后拆拆拆。。。推推推………………居然就…………推出来了………………
orz让我跪跪
orz其实根本不需要预处理
orz其实递推就可以了。。
让我来整理一下思路。。。(反正也不是我想出来的T_T)
首先 和大部分(不是所有)的数位dp一样 这个答案是可以相减的
也就是说 可以分开处理L和R再相减就可以了
但是这里的答案是solve(R) - solve(L)而不是L - 1 因为上界an * an+1是不算在答案里的而下界a1 * a2是算在答案里的
假设我们现在要求的是solve(X) 认为比X小的并且与X位数相等的幸运数字都是合法的(注意L和R位数是一样的)
把X的前n位取出来看成一个数C(比如说 X = 477444 i = 3时 C = 477)设Fn表示solve(C) Kn表示比C小与C位数相等的幸运数字个数。由定义 有:
如果已知Fi 那么 当X[n + 1] == 4时 有:
当X[n + 1] == 7时 有:
其实差别只在第一个sigma的上标 那么先考虑X[n + 1] == 4的情况:
将之前的定义式带入得:
然后可以发现:
那么带上去得:
然后。。。我们维护一个ai的和和一个ai^2的和再记录akn和a1还有kn 就可以递推了……
关于怎么维护……暴力拆一下 = =
然后……当X[i + 1] == 7的时候 我们把最后多出来的(10*ak+4)(10*ak+7)算上就行了。注意 ai == 10*ak+4而不是10*ak+7
因为我怕爆 long long 又觉得中途取模不好看。。所以用的是 unsigned long long = =但是乘的时候还是爆了T_T。。。。所以中途还是取了模。。。。。
那么其实代码一共只有39行。。但是它背后却是上面一堆乱七八糟丧心病狂非人哉的公式…………
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
typedef unsigned long long ULL;
const int Mod = 1000000007;
ULL solve()
{
string s; cin >> s; int len = s.size();
ULL F = 0llu, suq = 0llu, sum = 0llu, ak = 0llu, a1 = 0llu, K = 1llu;
for(int i = 0; i < len; ++i)
{
F = 100 * F + 100 * suq + 220 * sum + 70 * (ak + Mod - a1) % Mod + 56 * (K - 1); F %= Mod;
suq = 200 * suq + 220 * sum + 65 * (K - 1); suq %= Mod;
sum = 20 * sum + 11 * (K - 1); sum %= Mod;
if(s[i] ^ '4')
{
F += ((ak * 10 + 4) % Mod) * ((ak * 10 + 7) % Mod); F %= Mod;
suq += ((ak * 10 + 4) % Mod) * ((ak * 10 + 4) % Mod); suq %= Mod;
sum += ak * 10 + 4; sum %= Mod;
}
ak = ak * 10 + s[i] - '0'; ak %= Mod; a1 = a1 * 10 + 4; a1 %= Mod;
K = (K - 1) * 2; K += (s[i] == '4') ? 1 : 2; K %= Mod;
}
return F;
}
int main()
{
ios :: sync_with_stdio(false);
ULL res = -solve(); res += solve();
cout << (res + Mod) % Mod << endl;
return 0;
}
相关文章推荐
- 【数位dp && 优化数组范围】CodeForces - 55D Beautiful numbers
- 【动态规划】【数位DP】[Codeforces 55 D]Beautiful numbers
- Codeforces 55D Beautiful numbers 数位dp
- Codeforces Good bye 2015 B. New Year and Old Property dfs 数位DP
- Codeforces 55D Beautiful Number (数位dp)
- [数位DP][线性基]Codeforces 388D. Fox and Perfect Sets
- codeforces 55D - Beautiful numbers 数位DP+DFS
- codeforces 55D beautiful number [数学+数位DP]【动态规划+数论】
- CodeForces 55D 数位DP 能被它自身数位上的所有数整除
- 【codeforces】55D. Beautiful numbers 数位DP
- [数位DP] Codeforces 809C Round #415 (Div. 1) C. Find a car
- Magic Numbers codeforces 628D 数位dp
- Codeforces 809C [数位DP]
- CodeForces 54C-First Digit Law(数位,概率dp)
- codeforces 401D (数位DP)
- Codeforces 55d 数位dp
- CodeForces 628D Magic Numbers(数位DP)
- CodeForces 258B Little Elephant and Elections 数位DP
- Codeforces 55D - Beautiful numbers(数位dp)好
- codeforces_628D. Magic Numbers(数位dp)