题目描述

定义S(n)表示n的各个数位的k次方的和。定义$H(n)=min{n,S(n),H(S(n))}$。

求$$\sum _{i=A} ^{B} {H(i)} \mod 10000007$$

输入输出格式

输入格式:

一行三个数K、A、B。

【数据规模】

对于20%的数据,满足1≤A、B≤50;

对于100%的数据,满足1≤A、B≤10^6,K≤6.

输出格式:

B 一个数∑H(i) mod 10000007

i=A

输入输出样例

输入样例#1:

2 1 5
输出样例#1:

14

题解:

很暴力的解法,把每一个数都看作一个点,那么我们可以从一个数的每一位来得到它的下一个数,并向下一个数连一条有向边。

这样我们就得到了一个有向有环图,那么题意就变成了从一个点开始,一直向下走,所经过的所有点的最小值(包括环)。

考虑tarjan缩点,统计一下每一个强连通分量(也就是环)上的最小值。

很显然环上是没有出边的,我们将所有边反向,从入度为0的分量开始拓扑,一路上不断更新路径上的最小值,那么这样就统计出来了每一个点一直向下走,所经过的所有点的最小值。

然后把题目要求的点加在一起输出就可以了。(我用的是前缀和)

另外不要怀疑这道题会因为点过多而超时,当k=6时,以1~100000分别为起点,所经过的数的最大值是3188...(反正是个七位数),还是可以承受的。

时空复杂度O(能过)

 //Never forget why you start
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define mod (10000007)
using namespace std;
int n,t[];
bool vis[];
int suan(int x){
int ans=;
while(x){
ans+=t[x%];
x/=;
}
return ans;
}
int to[];
void dfs(int r){
if(vis[r])return;
vis[r]=;
int Next=suan(r);
to[r]=Next;
dfs(Next);
}
int dfn[],low[],sccno[],scc,dfscnt,mmin[];
int s[],top;
void tarjan(int r){
dfn[r]=low[r]=++dfscnt;
s[++top]=r;
int y=to[r];
if(!dfn[y]){
tarjan(y);
low[r]=min(low[r],low[y]);
}
else if(!sccno[y])low[r]=min(low[r],dfn[y]);
if(low[r]==dfn[r]){
scc++;
int x;
while(){
x=s[top--];
sccno[x]=scc;
mmin[scc]=min(x,mmin[scc]);
if(x==r)break;
}
}
}
struct node{
int next,to;
}edge[];
int size=;
void putin(int from,int to){
size++;
edge[size].to=to;
edge[size].next=dfn[from];
dfn[from]=size;
}
void bfs(){
queue<int>mem;
for(int i=;i<=scc;i++)if(!s[i])mem.push(i);
while(!mem.empty()){
int x=mem.front();mem.pop();
for(int i=dfn[x];i!=-;i=edge[i].next){
int y=edge[i].to;
mmin[y]=min(mmin[y],mmin[x]);
s[y]--;
if(!s[y])mem.push(y);
}
}
}
int main(){
int i,j;
scanf("%d",&n);
memset(mmin,/,sizeof(mmin));
for(i=;i<=;i++)t[i]=pow(i,n);
for(i=;i<=;i++){
dfs(i);
}
for(i=;i<=;i++)
if(!dfn[i])tarjan(i);
memset(dfn,-,sizeof(dfn));
memset(s,,sizeof(s));
for(i=;i<=;i++)
if(sccno[i]!=sccno[to[i]])putin(sccno[to[i]],sccno[i]),s[sccno[i]]++;
bfs();
low[]=;
for(i=;i<=;i++){
low[i]=mmin[sccno[i]];
(low[i]+=low[i-])%=mod;
}
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",(low[r]-low[l-]+mod)%mod);
return ;
}

[luogu 1660]数位平方和的更多相关文章

  1. 数位dp & 热身训练7

    数位dp 数位dp是一种计数用的dp,一般就是要统计一段区间$[L,R]$内,满足一定条件的数的个数,或者各个数位的个数. 数位dp使得暴力枚举变为满足一定状态的记忆化,更加优秀. 数位dp常常会考虑 ...

  2. Happy Number - LeetCode

    examination questions Write an algorithm to determine if a number is "happy". A happy numb ...

  3. Project Euler 92:Square digit chains C++

    A number chain is created by continuously adding the square of the digits in a number to form a new ...

  4. [luogu3413]萌数

    [luogu3413]萌数 luogu 考虑数位dp 怎么判断一个数是不是萌数? 只要知道其中某一位和它的前一位相等或者和前一位的前一位相等,那么它就是一个萌数 什么样的数不是萌数? 对于它的每一位都 ...

  5. Java判断一个数是不是快乐数

    快乐数的定义: 快乐数(happy number)有以下的特性: 在给定的进位制下,该数字所有数位(digits)的平方和,得到的新数再次求所有数位的平方和,如此重复进行,最终结果必为1. 以十进制为 ...

  6. LeetCode(202) Happy Number

    题目 Write an algorithm to determine if a number is "happy". A happy number is a number defi ...

  7. LeetCode 202: 快乐数 Happy Number

    题目: 编写一个算法来判断一个数是不是 "快乐数". 一个 "快乐数" 定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直 ...

  8. 清明 DAY 3

    ans=1000*4 分别固定千位,百位,十位,个位为1,其余位置随便排 对于每一个质因数的n次方,共有n+1中选择方法,即这个质因数的0~n次方 故共有   4*3*5=60  种方法 (1)取两册 ...

  9. 2021record

    2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...

随机推荐

  1. Project Web Server PSI 接口一些常用操作

    对Project Web Server进行二次开发,每天都把自己折腾到12点以后才休息,到处都是坑,研究那些烦人的PSI,国内根本查不到PSI相关的资料,对照API文档一点点谷歌资料,全部英文资料,开 ...

  2. Java Learning 000 搭建开发环境

    Java Learning 000 搭建开发环境 你需要两个软件: * JDK (Java Develop Kit :Java开发工具包) * eclipse (eclipse 集成开发环境软件) 安 ...

  3. Luogu 3825 [NOI2017]游戏

    Luogu的spj现在挂了,要去其他OJ提交. 2-SAT 发现如果不考虑$x$的情况,这就成为一个2-SAT的裸题了,我们有$O(n + m)$的方法可以解决它. 那加上$x$的情况怎么弄……岂不是 ...

  4. 1.4 如何防止sql注入

    如何防止sql注入   1.检查变量数据类型和格式 如果你的SQL语句是类似where id={$id}这种形式,数据库里所有的id都是数字,那么就应该在SQL被执行前,检查确保变量id是int类型: ...

  5. php小块代码

    //页面本身网址 "http://".$_SERVER["HTTP_HOST"].preg_replace("/[^\/]+$/",&quo ...

  6. 20169219《linux内核原理与分析》第六周作业

    网易云课堂学习 1.intel x86 CPU有四种不同的执行级别0-3,linux只使用了其中的0级和3级分贝来表示内核态和用户态. 2.一般来说在linux中,地址空间是一个显著的标志:0xc00 ...

  7. CRM 客户关系管理系统

    CRM(Customer Relationship Manager)客户关系管理系统 企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售.营销和服务上的交互,从而提升其管理方 ...

  8. DATASET()用法

    DataSet是ADO.NET的中心概念.可以把DataSet当成内存中的数据库,DataSet是不依赖于数据库的独立数据集合.所谓独立,就是说,即使断开数据链路,或者关闭数据库,DataSet依然是 ...

  9. If,for,range混合使用笔记-(VBA视频教程2:使用IF进行逻辑判断)

    -- 新建表格:#单元格a1-a100全部等于1的代码 Sub test() Dim i As Integer For i = To Range( Next End Sub -- 新建表格:#单元格a ...

  10. docker私有仓库的搭建

    Docker搭建本地私有仓库的详细步骤 Dockers不仅提供了一个中央仓库,同时也允许我们使用registry搭建本地私有仓库.使用私有仓库有许多优点:一.节省网络带宽,针对于每个镜像,不用每个人都 ...