您的位置:首页 > 产品设计 > UI/UE

【数位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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: