C. Bargain(数学规律+贡献法枚举优化)详解

   日期:2020-10-07     浏览:131    评论:0    
核心提示:https://codeforces.com/contest/1422/problem/C大晚上算错数据范围的我,以为只有50位,直接暴力T5.然后发现是10000位。贡献法优化,从低位往高位去枚举,也就是从后往前枚举。比如说枚举到第i位。考虑第i位前进行连续区间的取。设可以取的整个区间范围为k.可以发现,取1长的有k种,取2长的有k-2,取3长的有k-3...可以得出有k*(k+1)/2;代入长度(i-1)可以得如果在第i位前面去取的话,这个数位的贡献是i*(i-1)*s[i]*pow

https://codeforces.com/contest/1422/problem/C

大晚上算错数据范围的我,以为只有50位,直接暴力T5.然后发现是10000位。

贡献法优化,从低位往高位去枚举,也就是从后往前枚举。比如说枚举到第i位。

考虑第i位前进行连续区间的取。设可以取的整个区间范围为k.

可以发现,取1长的有k种,取2长的有k-2,取3长的有k-3...可以得出有k*(k+1)/2;

代入长度(i-1)可以得如果在第i位前面去取的话,这个数位的贡献是i*(i-1)*s[i]*pow[i];

考虑对第i位的后面的进行取。

举个例子。

8 4 3 2 1

对1来说,后面没有,那么贡献是0

对2来说,后面拿1,贡献是2

对3来说,后面拿1和2,贡献是3,后面拿1,贡献是30,后面拿2,贡献是30.

对4来说,后面拿123,贡献是4;后面拿23,21,贡献是40,40;后面拿3,2,1,贡献是400,400,400;

归纳起来就是

而后面的这个j*10^(j-1)可以累加更新得到。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
const LL mod=1e9+7;
LL sum[maxn];
char s[maxn];
int main(void)
{
  //cin.tie(0);std::ios::sync_with_stdio(false);
  cin>>(s+1);
  LL len=strlen(s+1);
  LL ans=0;
  LL pw=1;
  LL sum=0;
  for(LL i=len;i>=1;i--)
  {
  	LL num=i*(i-1)/2;
  	ans=(ans%mod+(s[i]-'0')*pw%mod*num%mod)%mod;
  	
	ans=(ans%mod+(s[i]-'0')%mod*sum%mod)%mod;
	
  	sum=(sum%mod+(len-i+1)*pw%mod)%mod;
  	
	pw=pw*10%mod;
  }
  cout<<ans<<endl;
return 0;
}

 

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服