Codeforces 288E Polo the Penguin and Lucky Numbers

8 篇文章 0 订阅

题目大意:

我们定义只含有4或者7的数为“幸运数”

现在给你L,R,问你L到R之间的幸运数的和

答案对10^9+7取模

(1<=l<r<=10^100000)



看到数字第一个想到的就是数位DP。

我们用sx[i][4]表示长度为i且开头为4的幸运数的和

用sx[i][7]表示长度为i且开头为7的幸运数的和

s[i][4]和s[i][7]分别表示长度为i的开头分别为4和7的幸运数个数

f[i][4]和f[i][7]分别表示长度为i的开头分别为4和7的ans

然后转移方程见程序,稍微手推一下应该就可以出来了

统计答案的时候从最高位开始减就可以了


#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long f[100001][8];
long long s[100001][8];
long long sx[100001][8];
long long mod=1000000007;
inline long long power(long long x,int y)
{
     long long t=1;
     while(y!=0)
     {
          if(y%2==1)
               t=t*x%mod;
          y=y/2;
          x=x*x%mod;
     }
     return t;
}
int main()
{
     //freopen("288E.in","r",stdin);
     //freopen("288E.out","w",stdout);
     string l,r;
     cin>>l>>r;
     int len=l.size();
     if(len==1)
     {
          if(l=="4"&&r=="7")
               printf("28\n");
          else
               printf("0\n");
          return 0;
     }
     f[2][4]=2068;
     s[2][4]=1;
     sx[2][4]=91;
     f[2][7]=5698;
     s[2][7]=1;
     sx[2][7]=151;
     sx[1][4]=4;
     sx[1][7]=7;
     long long x1=47,x2=74,xx=100;
     long long xx1=44,xx2=77;
     int i;
     for(i=3;i<=len;i++)
     {
     	  long long x4=(long long)4*xx%mod,x7=(long long)7*xx%mod;
     	  long long sxt=(long long)2*(sx[i-1][4]+sx[i-1][7])-xx1-xx2;
     	  sxt%=mod;
     	  while(sxt<0)
     	       sxt+=mod;
          f[i][4]=((f[i-1][4]+f[i-1][7]+x1*x2)%mod+(x4*x4%mod)*(s[i-1][4]+s[i-1][7]+(long long)1)%mod+x4*sxt%mod)%mod;
          f[i][7]=((f[i-1][4]+f[i-1][7]+x1*x2)%mod+(x7*x7%mod)*(s[i-1][4]+s[i-1][7]+(long long)1)%mod+x7*sxt%mod)%mod;
          s[i][4]=(s[i-1][4]+s[i-1][7]+(long long)1)%mod;
          s[i][7]=(s[i-1][4]+s[i-1][7]+(long long)1)%mod;
          sx[i][4]=(sx[i-1][4]+sx[i-1][7]+x4*(s[i][4]+(long long)1)%mod)%mod;
          sx[i][7]=(sx[i-1][4]+sx[i-1][7]+x7*(s[i][7]+(long long)1)%mod)%mod;
          x1=(x1*(long long)10+(long long)7)%mod;
          x2=(x2*(long long)10+(long long)4)%mod;
          xx=xx*(long long)10%mod;
          xx1=(xx1*(long long)10+(long long)4)%mod;
          xx2=(xx2*(long long)10+(long long)7)%mod;
     }
     long long px=power(10,mod-2);
     long long ans=(f[len][4]+f[len][7]+x1*x2)%mod;
     long long x4=0;
     long long tx1=x1,tx2=x2,txx=xx;
     for(i=len;i>=1;i--)
     {
     	  int dx=len-i;
          if(l[dx]=='7')
          {
               long long xt=x4*xx%mod;
               long long sxt=((long long)2*sx[i][4]-xx1-x1)%mod;
               while(sxt<0)
                    sxt+=mod;
               long long tt=(f[i][4]/*+x1*x2*/+(xt*xt%mod)*(s[i][4]/*+(long long)1*/)%mod+xt*sxt%mod)%mod;
               tt=(tt+(xt+x1)*(xt+x2)%mod)%mod;
               ans-=tt;
               while(ans<0)
                    ans+=mod;
          }
          x4=(x4*(long long)10+(long long)(l[dx]-'0'))%mod;
          x4%=mod;
          xx=xx*px%mod;
          x1=(x1-(long long)7)*px%mod;
          while(x1<0)
               x1+=mod;
          x2=(x2-(long long)4)*px%mod;
          while(x2<0)
               x2+=mod;
          xx1=(xx1-(long long)4)*px%mod;
          while(xx1<0)
               xx1+=mod;
     }
     
     long long x7=0;
     x1=tx1;
     x2=tx2;
     xx=txx;
     for(i=len;i>=1;i--)
     {
     	  int dx=len-i;
          if(r[dx]=='4')
          {
               long long xt=x7*xx%mod;
               long long sxt=((long long)2*sx[i][7]-xx2-x2)%mod;
               while(sxt<0)
                    sxt+=mod;
               long long tt=(f[i][7]/*+x1*x2*/+(xt*xt%mod)*(s[i][7]/*+(long long)1*/)%mod+xt*sxt%mod)%mod;
               tt=(tt+(xt+x1)*(xt+x2)%mod)%mod;
               ans-=tt;
               while(ans<0)
                    ans+=mod;
          }
          x7=(x7*(long long)10+(long long)(r[dx]-'0'))%mod;
          x7%=mod;
          xx=xx*px%mod;
          x1=(x1-(long long)7)*px%mod;
          while(x1<0)
               x1+=mod;
          x2=(x2-(long long)4)*px%mod;
          while(x2<0)
               x2+=mod;
          xx2=(xx2-(long long)7)*px%mod;
          while(xx2<0)
               xx2+=mod;
     }
     
     printf("%I64d\n",ans);
     return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值