XMUT ACdream DP专场E题 - 喵哈哈的日常选数问题(数位DP)

本文介绍了一种算法,用于计算在指定范围内不包含特定数字模式(如37或4)的整数数量。通过使用动态规划方法预先计算所有可能数字组合的有效数量,并通过数位DP来快速查询任意范围内的结果。


Problem Description

喵哈哈村子的TTT同学比较怪,他非常讨厌一类数字,是哪种呢?

就是讨厌那些含有37或者4的数

比如 21379,123485,12379。

但是他并不讨厌928357这个数,因为他即不包含37,也没有4。

 

现在你[L,R]的区间,问你在这个区间中,最多能够选出多少个TTT同学不讨厌的数呢?

Input

输入两个整数,表示L和R

1 <= L <= R <= 2000000000 。

Output
输出一个整数,表示选出的数的个数
Sample Input
1 10
Sample Output
9


分析:解题思想参见我的另一篇博客:http://blog.youkuaiyun.com/enjoying_science/article/details/44082929

AC code:

#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<cmath>
#define LL long long
using namespace std;
const LL INF=0x3f3f3f3f;
const int weishu=11;
int L,R;
LL dp[1005][1005];//dp[i][j]表示以j开头的i位数满足题目条件的个数 
LL ans=0;
void init()
{
	int i,j,k;
	memset(dp,0,sizeof(dp));//初始化 
	dp[0][0]=1;//初始化 
	for(i=1;i<=weishu;i++)
	{
		for(j=0;j<=9;j++)//当前位 
		{
			for(k=0;k<=9;k++)//当前位的下一位 
			{
				if(j!=4&&!(j==3&&k==7))
				{
					dp[i][j]+=dp[i-1][k];
				}
			}
		}
	}
 }
LL solve(LL x)
{
	int len=0;
	int digit[11];
	int i,j,k;
	while(x)
	{
		digit[++len]=x%10;
		x/=10;
	}
	digit[++len]=0;//数位DP时必须再加个前导0 
	LL cnt=0;
	for(i=len;i>0;i--)//从高位向低位逐个数位DP 
	{
		for(j=0;j<digit[i];j++)//j表示小于当前位的数 
		{
			if(j!=4&&!(digit[i+1]==3&&j==7))//满足题目条件 
			{
				cnt+=dp[i][j];
			}
		}
		if(digit[i]==4||(digit[i+1]==3&&digit[i]==7))//因为是从高位到低位搞的,当前位不符合时,
		{											//接下来小于它的数都不符合,所以直接结束  
			break;
		}
	}
	return cnt;
}  
int main()
{
	init();
	while(scanf("%lld%lld",&L,&R)!=EOF)
	{
		ans=solve(R+1)-solve(L);//solve(x+1)求的是小于等于x的数中符合题目条件的个数,相减即得区间的个数 
		printf("%lld\n",ans);
	}
    return 0;
}



package sfw.xmut.guomao.aspect; import sfw.xmut.guomao.entity.OperationLog; import sfw.xmut.guomao.mapper.OperationLogMapper; import sfw.xmut.guomao.utils.ServletUtil; import jakarta.servlet.http.HttpServletRequest; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.time.LocalDateTime; @Aspect @Component public class OperationLogAspect { private final OperationLogMapper logMapper; public OperationLogAspect(OperationLogMapper logMapper) { this.logMapper = logMapper; } @Around("execution(* sfw.xmut.guomao.controller.*.*(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = attributes.getRequest(); if (request.getRequestURI().endsWith("/operationLog/page")) { return joinPoint.proceed(); } long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long spendTime = System.currentTimeMillis() - startTime; OperationLog log = new OperationLog(); log.setUserName("admin"); // TODO: Get from JWT token log.setOperationType(request.getRequestURI()); log.setOperationMethod(request.getMethod()); log.setRequestUrl(request.getRequestURL().toString()); log.setOperationIp(ServletUtil.getClientIP(request)); log.setOperationStatus("成功"); log.setLastOperationTime(LocalDateTime.now()); logMapper.insert(log); return result; } }log.setUserName("admin"); // TODO: Get from JWT token 这一行代码怎么把他改成不管哪个用户登录这个管理系统日志上面都可以更新,不要像这个admin锁住固定住不管谁登录都是显示他的名称
06-19
<think>我们正在处理一个关于从JWTtoken中获取当前登录用户名并动态设置到OperationLog对象的userName字段中的问题。根据引用[2],我们知道JWTtoken由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。其中,载荷部分包含了用户信息,如用户ID、用户名等。因此,我们需要做以下几步:1.在用户登录成功后,服务器会生成一个JWTtoken并返回给客户端。客户端在后续请求中会携带这个token(通常在HTTP请求的Authorization头中)。2.在服务器端,我们需要从请求中获取这个token。3.然后,解析这个token,提取出载荷(Payload)中的用户名。4.最后,在创建OperationLog对象时,将解析得到的用户名设置到userName字段。具体实现步骤可能因使用的编程语言和框架而有所不同。下面以几种常见的语言为例说明。注意:在解析JWTtoken时,需要验证token的签名以确保其未被篡改,并且检查token的过期时间。引用[3]给出了Go语言使用JWT生成token以及获取token中信息的示例。我们可以参考它来解析token。下面分别用几种语言示例如何从JWTtoken中获取用户名:1.Java(使用SpringBoot和jjwt库)2.Python(使用PyJWT)3.Go(使用jwt-go库)由于问题中没有指定语言,我们将以Java为例(因为SpringBoot在Java中很流行),并简要说明其他语言。假设我们有一个SpringBoot应用,并且使用jjwt库来处理JWT。步骤:a.添加依赖(在pom.xml中):<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.5</version><scope>runtime</scope></dependency>b.在拦截器或过滤器中解析token(或者直接在需要的地方解析):通常,我们会有一个拦截器来拦截请求,从请求头中获取token,然后解析。c.解析token并获取用户名:示例代码(在拦截器中):```javaimportio.jsonwebtoken.Claims;importio.jsonwebtoken.Jwts;//...其他导入publicclassJwtInterceptorimplementsHandlerInterceptor{privatefinalStringsecretKey="your-secret-key";//与生成token时使用的密钥相同@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{Stringtoken=request.getHeader("Authorization");if(token!=null&&token.startsWith("Bearer")){token=token.substring(7);//去掉"Bearer"try{Claimsclaims=Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token).getBody();//假设我们在生成token时在claims中存储了用户名,键为"username"Stringusername=claims.get("username",String.class);//将用户名存储在请求属性中,以便后续使用request.setAttribute("username",username);}catch(Exceptione){//token无效或过期response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);returnfalse;}}else{//没有tokenresponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);returnfalse;}returntrue;}}```d.然后在记录日志的地方(例如Controller或Service中),我们可以从请求属性中获取用户名并设置到OperationLog对象:```java@PostMapping("/some-operation")publicResponseEntity<?>someOperation(HttpServletRequestrequest){//获取用户名Stringusername=(String)request.getAttribute("username");OperationLoglog=newOperationLog();log.setUserName(username);//动态设置用户名//...其他操作//然后保存日志等操作}```注意:上述代码只是一个示例,实际应用中可能需要更完善的错误处理和日志记录。对于其他语言:Python(使用PyJWT)示例:```pythonimportjwttoken=request.headers.get('Authorization').split('')[1]#假设格式为"Bearer<token>"payload=jwt.decode(token,'your-secret-key',algorithms=['HS256'])username=payload['username']```Go(使用jwt-go)示例,参考引用[3]:```goimport("github.com/dgrijalva/jwt-go")tokenString:=strings.Split(request.Header.Get("Authorization"),"")[1]//获取token部分token,err:=jwt.Parse(tokenString,func(token*jwt.Token)(interface{},error){return[]byte("your-secret-key"),nil})ifclaims,ok:=token.Claims.(jwt.MapClaims);ok&&token.Valid{username:=claims["username"].(string)//使用username}else{//处理错误}```总结:关键步骤是解析JWTtoken的载荷部分,从中取出用户名。在实现时,注意安全性和错误处理。另外,如果用户没有提供token或token无效,应该返回401未授权错误。这样,我们就可以动态地将当前登录的用户名设置到OperationLog对象的userName字段中,而不是固定为'admin'。相关问题1.JWTtoken的安全性如何保障?2.除了拦截器,还有哪些地方可以解析JWTtoken?3.如何设计一个操作日志记录系统?</think>### 从JWT Token获取登录用户名并设置到日志对象 要实现动态获取JWT中的用户名并设置到`OperationLog`对象,需完成以下步骤: #### 1. **解析JWT Token** JWT Token包含头部(Header)、载荷(Payload)和签名(Signature)三部分[^2]。用户名通常存储在Payload中: ```javascript // JWT Payload示例 { "sub": "user123", "username": "张三", // 包含用户名的字段 "exp": 1735689600 } ``` #### 2. **后端实现步骤(以Java/Spring Boot为例)** ```java // 1. 从请求头获取Token String token = request.getHeader("Authorization").replace("Bearer ", ""); // 2. 解析Token并提取用户名 public String extractUsername(String token) { Claims claims = Jwts.parserBuilder() .setSigningKey(secretKey) // 使用服务器密钥验证签名 .build() .parseClaimsJws(token) .getBody(); return claims.get("username", String.class); // 从Payload获取用户名 } // 3. 动态设置到日志对象 OperationLog log = new OperationLog(); log.setUserName(extractUsername(token)); // 动态注入用户名 ``` #### 3. **关键注意事项** - **字段一致性**:确保代码中的字段名(如`username`)与JWT Payload中的声明一致 - **安全验证**:必须验证签名防止篡改,参考JWT规范[^2] - **错误处理**:添加`try-catch`处理过期/无效Token - **框架集成**:Spring Security可通过`@AuthenticationPrincipal`自动注入: ```java @PostMapping("/log") public void recordLog(@AuthenticationPrincipal User user) { OperationLog log = new OperationLog(); log.setUserName(user.getUsername()); // 自动获取当前用户 } ``` #### 4. **其他语言示例** - **Go语言**(参考引用[^3]): ```go token, _ := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return secretKey, nil }) claims := token.Claims.(jwt.MapClaims) userName := claims["username"].(string) ``` - **Python (PyJWT)**: ```python payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) username = payload["username"] ``` ### 实现效果 - 用户A登录 → JWT包含`"username": "A"` → 日志显示用户A的操作 - 用户B登录 → 自动切换为B的用户名 - 彻底替代固定值`admin` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值