妈蛋真是脑洞大开!
看看这个交错和问题:
各种溢出和逻辑上错误导致的越界、对象错误防不胜防。
描述
给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数:
f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1
例如:
f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4
给定
输入
输入数据仅一行包含三个整数,l, r, k(0 ≤ l ≤ r ≤ 1018, |k| ≤ 100)。
输出
输出一行一个整数表示结果,考虑到答案可能很大,输出结果模 109 + 7。
提示
对于样例 ,满足条件的数有 110 和 121,所以结果是 231 = 110 + 121。
更多样例:
Input |
4344 3214567 3 |
Output |
611668829 |
Input |
404491953 1587197241 1 |
Output |
323937411 |
Input |
60296763086567224 193422344885593844 10 |
Output |
608746132 |
Input |
100 121 -1 |
Output |
120 |
100 121 0
231
状态:
[i][j][k]
边界:
- i=[0,len(x)) ,len即x的十进制位数。
- k属于[0,n),其中0对应minN,n-1对应maxN. 所以n=maxN-minN+1.
递推方程:
- E{cnt[i][j][k]} = _cnt[i][k] => cnt[i+1][j][k+(-1)^(i+1)*j]
- E{num[i][j][k]} = _num[i][k], _num[i][k]+_cnt[i][k] * 10^(i+1) => num[i+1][j][k+(-1)^(i+1)*j]
#include <iostream>
#include <vector>
#include <assert.h>
#include <math.h>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll> Pair;//@pair<int,ll> can overflow!!! should be pair<ll,ll>
#define MOD 1000000007
int dump(ll x,int a[]){
int i=0;while(x>0){ a[i++]=x%10;x/=10; }
if(i==0) a[0]=0,i=1;
return i;
}
ll dp(ll x, int K){
// return the count of number in [0~x) that f(number)=K
if(x==0) return 0;
int a[18];int len=dump(x,a);
int minN=0-(len/2)*9,maxN=(len+1)/2*9;//0909.. 9090..
if(K<minN||K>maxN) return 0;
int delta=0-minN,n=maxN-minN+1;
p[i][j][k] : delta+ (+/-)xi .... -x1 + x0 = k, xi = j
vector<vector<vector<Pair> > > p(len,vector<vector<Pair> >(10,
vector<Pair>(n,Pair(0,0))));
//init
for(int j=0;j<10;j++) p[0][j][j+delta]=Pair(1,j); i=0. j=x0, x0+delta=k
for(int i=0;i<len-1;i++){
vector<Pair> cnt(n,Pair(0,0));
for(int j=0;j<10;j++){
for(int k=0;k<n;k++){
Pair &s=p[i][j][k];
cnt[k].first=(s.first+cnt[k].first)%MOD;
cnt[k].second=(s.second+cnt[k].second)%MOD;
}
}
// [i][k] => [i+1][j][k+(+/-)j]
for(int j=0;j<10;j++){
int fh=pow(-1,i+1);
ll d=(ll)pow(10,i+1)%MOD*j%MOD;//@error:pow(10,i+1)*j can overflow
for(int k=0;k<n;k++){
if(k+fh*j<0||k+fh*j>=n) continue;//@attention: here k+fh*j can be unavailable
Pair &s=p[i+1][j][k+fh*j];
s.first=cnt[k].first;
assert(d<MOD);
assert(s.first<MOD);
s.second=(d*s.first%MOD+cnt[k].second)%MOD;
}
}
}
// count of number in [0~xm..x3x2x1x0] , where m<len-1
ll num=0;
//int b[len];
for(int i=len-2;i>=0;i--){
//b[i+1]=0;
int j;
int fh=pow(-1,i);
if(i==0) j=0;
else j=1;
if(fh==1) (k-delta)=K; else -(k-delta)=K
int k=fh*K+delta;
if(!(k>=0&&k<n)) continue;//here k can be unavailable
// assert(k>=0&&k<n);//@error: logic error, here k can be out of [0,n)
for(;j<10;j++){
//b[i]=j;
num=(num+p[i][j][k].second)%MOD;
}
}
//count of number in [10000...00,x)
ll s=0;
int lst=0;
int fh=pow(-1,len-1);
for(int i=len-1;i>=0;i--){
int j;
if(i==len-1) j=1;
else j=0;
int k=(K-lst)*fh+delta;
// assert(k>=0&&k<n);//@error: logic error, here k can be out of [0,n)
if(!(k>=0&&k<n)) ;//@attention: k can be unavailable
else
for(;j<a[i];j++){
lst+fh*(k-delta)=K, k=(K-lst)/fh+delta
Pair &q=p[i][j][k];
ll d=(q.second+s*q.first%MOD)%MOD;
num=(num+d)%MOD;
}
lst+=pow(-1,i)*fh*a[i];
// s+=pow(10,i)*a[i]; //@error: here s will overflow!!!!
s=(s+(ll)pow(10,i)*a[i]%MOD)%MOD;
//@attention: (ll) has higher priority than *
//@attention: pow(10,i)*a[i] will not overflow
}
return num;
}
int main(){
ll l,r;int k;
debug
// for(r=999999;r<999999999;r+=10000){
// for(k=1;k<100;k++){
// cout<<dp(r,k)<<endl;
// }
// }
cin>>l>>r>>k;
ll x1=dp(l,k);
ll x2=dp(r,k);
ll cnt=(x2-x1)%MOD;
int b[18];int len=dump(r,b);
int fh=pow(-1,len-1);int kk=0;
for(int i=len-1;i>=0;i--) kk+=fh*pow(-1,i)*b[i];
// if(kk==k) cnt++;//@error: logic error: cnt++ should be cnt+=r
if(kk==k) cnt=(cnt+r%MOD)%MOD;
cout<<(cnt+MOD)%MOD<<endl;
return 0;
}
或者:
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long LL;
const LL Mod=1000000007;
int k0;
LL cnt[20][20*9], sum[20][20*9];
void dp(int n)
{
int sign=-1;
cnt[0][k0]=1; sum[0][k0]=0;
for (int i=0; i<n; ++i)
{
sign=-sign;
for (int j=-i/2*9; j<=(i+1)/2*9; ++j)
for (int l=0; l<=9; ++l)
{
int x=j+sign*l+k0;
cnt[i+1][x]=(cnt[i+1][x]+cnt[i][j+k0])%Mod;
sum[i+1][x]=(sum[i+1][x]+sum[i][j+k0]*10+cnt[i][j+k0]*l)%Mod;
}
}
}
LL calc(int n, int k)
{
if (n<=0) return 0;
LL res=calc(n-1, k);
LL base=1;
for (int i=1; i<n; ++i) base*=10;
for (int i=1; i<=9; ++i) res=(res+i*base%Mod*cnt[n-1][i-k+k0]+sum[n-1][i-k+k0])%Mod;
return res;
}
LL work(LL num, int k)
{
int n=0, a[20];
LL base=1;
for (LL x=num; x; x/=10) a[n++]=x%10, base*=10;
int sign=-1, k1=k;
LL res=calc(n-1, k), pre=0;
for (int i=n-1; i>=0; --i)
{
base/=10;
sign=-sign;
pre*=10;
for (int j=(i==n-1? 1:0); j<a[i]; ++j)
{
int suc=(k1-j*sign)*(-sign)+k0;
res=(res+(pre+j)*base%Mod*cnt[i][suc]+sum[i][suc])%Mod;
}
pre+=a[i];
k1-=a[i]*sign;
}
if (k1==0) res=(res+pre)%Mod;
return res;
}
int main()
{
LL l, r;
int k;
cin>>l>>r>>k;
int n=0;
for (LL x=r; x; x/=10) ++n;
k0=n/2*9;
dp(n);
cout<<((work(r, k)-work(l-1, k))%Mod+Mod)%Mod<<endl;
return 0;
}
另一种写法
//#pragma comment(linker,"/STACK:102400000,102400000")
template<class T> inline T sqr(T x) { return x * x; }
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<PII, int> PIII;
typedef pair<LL, LL> PLL;
typedef pair<LL, int> PLI;
typedef pair<LD, LD> PDD;
#define MP make_pair
#define PB push_back
#define sz(x) ((int)(x).size())
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define istr stringstream
#define FOR(i,n) for(int i=0;i<(n);++i)
#define forIt(mp,it) for(__typeof(mp.begin()) it = mp.begin();it!=mp.end();it++)
const double PI = acos(-1.0);
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define lowbit(u) (u&(-u))
using namespace std;
#define MOD 1000000007
PLL dp[25][205][2][2];
int digit[25];
LL l,r,k,p10[25];
PLL dfs(int cur,int sum,int x,int lead,int limit){
if(cur<0){
if(sum==k) return MP(0,1);
return MP(0,0);
}
if(!limit&&~dp[cur][sum][x][lead].first) return dp[cur][sum][x][lead];
if(!lead) x = 1;
LL ans = 0,cnt = 0;
int ed = limit?digit[cur]:9;
int p = 1;
if(x==0) p = -1;
for(int i = 0;i<=ed;i++){
PLL ret = dfs(cur-1,sum+i*p,!x,lead||i,limit&&i==ed);
ans+=i*p10[cur]%MOD*ret.second%MOD+ret.first;
ans%=MOD;
cnt+=ret.second;
cnt%=MOD;
}
if(!limit) dp[cur][sum][x][lead] = MP(ans,cnt);
return MP(ans,cnt);
}
PLL solve(LL n){
if(n<0) return MP(0,0);
int cnt = 0;
while(n){
digit[cnt++] = n%10;
n/=10;
}
return dfs(cnt-1,100,1,0,1);
}
int main(void){
#ifndef ONLINE_JUDGE
//freopen("/Users/mac/Desktop/data.in","r",stdin);
#endif
p10[0] = 1;
for(int i = 1;i<=20;i++) p10[i] = 1ll*p10[i-1]*10%MOD;
memset(dp,-1,sizeof(dp));
scanf("%lld %lld %lld",&l,&r,&k);
k+=100;
LL ret = solve(r).first-solve(l-1).first;
if(ret<0) ret+=MOD;
printf("%lld\n",ret);
return 0;
}
或者
#pragma comment(linker, "/STACK:36777216")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lc(x) (x << 1)
#define rc(x) (lc(x) + 1)
#define lowbit(x) (x & (-x))
#define PI (acos(-1))
#define lowbit(x) (x & (-x))
#define EPS 1e-10
#define MAXN 100005
#define MAXM 2005
#define LL long long
#define DB double
#define ULL unsigned long long
#define PII pair<int, int>
#define INF 0x3fffffff
#define PB push_back
#define MP make_pair
#define MOD 1000000007
using namespace std;
LL f[20][405][2][2], f2[20][405][2][2], ten[20], dig[20];
LL Mul(LL a, LL b){
a %= MOD, b %= MOD;
return (a * b) % MOD;
}
int K;
LL dp(int pos, int sum, bool first, bool ud, bool flag){
if(sum < 0 || sum > 400) return 0;
if(pos == -1) return (sum == (200 + K));
if(!flag && f[pos][sum][first][ud] != -1)
return f[pos][sum][first][ud];
LL res = 0;
for(int i = 0, l = flag ? dig[pos] : 9; i <= l; i ++){
if(first == true){
if(i == 0) res += dp(pos - 1, sum, 1, 0, flag && i == l);
else res += dp(pos - 1, sum + i, 0, 1, flag && i == l);
}
else{
int tmp;
if(ud == 0) tmp = sum + i; else tmp = sum - i;
res += dp(pos - 1, tmp, 0, !ud, flag && i == l);
}
res %= MOD;
}
return flag ? res : f[pos][sum][first][ud] = res;
}
LL dp2(int pos, int sum, bool first, bool ud, bool flag){
if(sum < 0 || sum > 400) return 0;
if(pos == -1) return 0;
if(!flag && f2[pos][sum][first][ud] != -1)
return f2[pos][sum][first][ud];
LL res = 0;
for(int i = 0, l = flag ? dig[pos] : 9; i <= l; i ++){
LL has = 0;
if(first == true){
if(i == 0) has = dp(pos - 1, sum, 1, 0, flag && i == l), res += dp2(pos - 1, sum, 1, 0, flag && i == l);
else has = dp(pos - 1, sum + i, 0, 1, flag && i == l), res += dp2(pos - 1, sum + i, 0, 1, flag && i == l);
}
else{
int tmp;
if(ud == 0) tmp = sum + i; else tmp = sum - i;
has = dp(pos - 1, tmp, 0, !ud, flag && i == l);
res += dp2(pos - 1, tmp, 0, !ud, flag && i == l);
}
res %= MOD;
LL tmp;
tmp = (LL) i * ten[pos] % MOD;
tmp = (tmp * has) % MOD;
res = (res + tmp) % MOD;
//res += Mul(Mul((LL) i, ten[pos]), has);
res %= MOD;
}
return flag ? res : f2[pos][sum][first][ud] = res;
}
LL calc(LL x){
if(x < 0) return 0;
int cnt = 0;
while(x)
dig[cnt ++] = x % 10, x /= 10;
return dp2(cnt - 1, 200, 1, 0, 1) % MOD;
}
int t; LL l, r;
int main(){
//freopen("in.txt", "r", stdin);
ten[0] = 1;
for(int i = 1; i < 20; i ++)
ten[i] = (ten[i - 1] * 10) % MOD;
while(cin >> l >> r >> K){
memset(f, -1, sizeof(f)); memset(f2, -1, sizeof(f2));
LL k2 = calc(r), k1 = calc(l - 1);
LL ans = (k2 - k1 + MOD) % MOD;
cout << ans << endl;
//printf("%lld\n", ans);
}
}
或者:
/*
* temp.cpp
*
* Created on: 2012-7-18
* Author: BSBandme
*/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <cassert>
#include <list>
#include <iomanip>
#include <math.h>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <climits>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <tr1/unordered_set>
#include <tr1/unordered_map>
using namespace std;
using namespace tr1;
#define mpr make_pair
typedef unsigned int ui;
typedef unsigned long long ull;
typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <double, double> pdd;
typedef vector <int> vi;
typedef vector <ll> vll;
typedef vector <double> vd;
typedef vector <string> vs;
typedef map <string, int> mpsi;
typedef map <double, int> mpdi;
typedef map <int, int> mpii;
const double pi = acos(0.0) * 2.0;
const double eps = 1e-12;
const int step[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
template <class T> inline T abs1(T a) {return a < 0 ? -a : a;}
template <class T> inline T max1(T a, T b) { return a > b ? a : b; }
template <class T> inline T max1(T a, T b, T c) { return max1(max1(a, b), c); }
template <class T> inline T max1(T a, T b, T c, T d) { return max1(max1(a, b, c), d); }
template <class T> inline T max1(T a, T b, T c, T d, T e) { return max1(max1(a, b, c, d), e); }
template <class T> inline T min1(T a, T b) { return a < b ? a : b; }
template <class T> inline T min1(T a, T b, T c) { return min1(min1(a, b), c); }
template <class T> inline T min1(T a, T b, T c, T d) { return min1(min1(a, b, c), d); }
template <class T> inline T min1(T a, T b, T c, T d, T e) { return min1(min1(a, b, c, d), e); }
inline int jud(double a, double b){
if(abs(a) < eps && abs(b) < eps) return 0;
else if(abs1(a - b) / abs1(a) < eps) return 0;
if(a < b) return -1;
return 1;
}
template <typename t> inline int jud(t a, t b){
if(a < b) return -1;
if(a == b) return 0;
return 1;
}
// f_lb == 1代表返回相同的一串的左边界,f_small == 1代表返回如果没有寻找的值返回小的数
template <typename it, typename t1>
inline int find(t1 val, it a, int na, bool f_small = 1, bool f_lb = 1){
int be = 0, en = na - 1;
if(*a <= *(a + na - 1)){
if(f_lb == 0) while(be < en){
int mid = (be + en + 1) / 2;
if(jud(*(a + mid), val) != 1) be = mid;
else en = mid - 1;
}else while(be < en){
int mid = (be + en) / 2;
if(jud(*(a + mid), val) != -1) en = mid;
else be = mid + 1;
}
if(f_small && jud(*(a + be), val) == 1) be--;
if(!f_small && jud(*(a + be), val) == -1) be++;
} else {
if(f_lb) while(be < en){
int mid = (be + en + 1) / 2;
if(jud(*(a + mid), val) != -1) be = mid;
else en = mid - 1;
}else while(be < en){
int mid = (be + en) / 2;
if(jud(*(a + mid), val) != 1) en = mid;
else be = mid + 1;
}
if(!f_small && jud(*(a + be), val) == -1) be--;
if(f_small && jud(*(a + be), val) == 1) be++;
}
return be;
}
template <class T> inline T lowb(T num) {return num & (-num); }
inline int bitnum(ui nValue) { return __builtin_popcount(nValue); }
inline int bitnum(int nValue) { return __builtin_popcount(nValue); }
inline int bitnum(ull nValue) { return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32); }
inline int bitnum(ll nValue) { return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32); }
inline int bitmaxl(ui a) { if(a == 0) return 0; return 32 - __builtin_clz(a); }
inline int bitmaxl(int a) { if(a == 0) return 0; return 32 - __builtin_clz(a); }
inline int bitmaxl(ull a) { int temp = a >> 32; if(temp) return 32 - __builtin_clz(temp) + 32; return bitmaxl(int(a)); }
inline int bitmaxl(ll a) { int temp = a >> 32; if(temp) return 32 - __builtin_clz(temp) + 32; return bitmaxl(int(a)); }
long long pow(long long n, long long m, long long mod = 0){
if(m < 0) return 0;
long long ans = 1;
long long k = n;
while(m){
if(m & 1) {
ans *= k;
if(mod) ans %= mod;
}
k *= k;
if(mod) k %= mod;
m >>= 1;
}
return ans;
}
#define MOD 1000000007
template <class t1, class t2>
inline void add(t1 &a, t2 b, int mod = -1) {
if(mod == -1) mod = MOD;
a += b;
while(a >= mod) a -= mod;
while(a < 0) a += mod;
}
//#define debug
//.........................mi.......feng......xian.......xia.......jin.......zhi.......hack...............................................