超大整数开方&&灯

本文解析了T4607灯谜题,介绍了如何通过计算完全平方数来确定操作后亮灯的数量,并提供了一种快速计算方法——手动开根法。

引用:点击打开链接

T4607 灯·重回江湖收五杀【提高】
题目描述
N盏灯和N个人,最开始N盏灯都是灭的,第i个人会按下第ki(ki≤N且k>0)的开关,试问N个人操作之后有多少盏灯是亮着的。
输入输出格式
输入格式:
输入共一个正整数N
输出格式:
输出共一个正整数,即N个人操作之后亮着的灯的数量。
输入输出样例
输入样例#1:
2
输出样例#1:
1
说明
test_point N的长度
1-2 2
3-6 10
7-10 100
11-20 200

很显然,第i盏灯会被操作i的因数个数次,因此最终开着的灯的序号的因数个数都是奇数。而因数个数是奇数的正整数就是完全平方数。因此题意就是求n及以下的正整数中完全平方数的个数。求法就是直接开n的方。

引用:点击打开链接

首先我是一个蒟蒻23333所以我不会一些奇怪的东西比如暴力二分做这个题 
then 
有一个奇怪的东西叫做手动开根: 
手动开根号的基本方法: 
1. 将被开方数从右向左每隔2位用撇号分开; 
2. 从左边第一段求得算数平方根的第一位数字; 
3. 从第一段减去这个第一位数字的平方,再把被开方数的第二段写下来,作为第一个余数; 
4. 把所得的第一位数字乘以20,去除第一个余数,所得的商的整数部分作为试商(如果这个整数部分大于或等于10,就改用9左试商,如果第一个余数小于第一位数字乘以20的积,则得试商0); 
5. 把第一位数字的20倍加上试商的和,乘以这个试商,如果所得的积大于余数时,就要把试商减1再试,直到积小于或等于余数为止,这个试商就是算数平方根的第二位数字; 
6. 用同样方法继续求算数平方根的其他各位数字。

example: 
这里写图片描述 
so 我们就获得了一种神奇的方法来做这道题切拥有更快的速度和更高的复杂度。


#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

int l;
int work(int o,char *O,int I)
{
    char c, *D=O ;
    if(o>0)
    {
        for(l=0;D[l];D[l++]-=10)
        {
            D[l++]-=120;
            D[l]-=110;
            while(!work(0,O,l))
                D[l]+=20;
            putchar((D[l]+1032)/20);
        }
        putchar(10);
    }
    else
    {
        c=o+(D[I]+82)%10-(I>l/2)*(D[I-l+I]+72)/10-9;
        D[I]+=I<0 ? 0 : !(o=work(c/10,O,I-1))*((c+999)%10-(D[I]+92)%10);
    }
    return o;
}

int main()
{
    char s[1200];s[0]='0';
    scanf("%s",s+1);
    if(strlen(s)%2 == 1)
        work(2,s+1,0);
    else
        work(2,s,0);
    return 0;
}

/******************************************************************************* @file HDL_WS2812B.c @author huiyang @version V1.0 @date 01/21/2022 ****************************************************************************/ #include “HDL_WS2812B.h” #include “stm32f10x.h” // Device header #include <math.h> #include “Delay.h” //延时函加自己对应的头文件,在复位处使用 #include “OLED.h” uint32_t mode1[3] = {0xff0000,0x00ff00,0x0000ff};//绿红蓝 uint32_t mode2[3] = {0xffffff,0x00ff00,0x0000ff};//白红蓝 uint32_t mode3[3] = {0x0000ff,0x00ff00,0xffffff};//蓝红白 uint32_t mode_red[1] = {0x00ff00};//红 Bst arr[4] = { {0, 0, 0, mode1, 3}, // arr[0] {0, 0, 0, mode2, 3}, // arr[1] {0, 0, 0, mode3, 3}, // arr[2] {0, 0, 0, mode_red, 1} }; / 单个珠的编码对应的比较值组 / uint16_t Single_LED_Buffer[DATA_SIZELED_NUM]; uint16_t All_LED_DE[LED_NUM]; / *作用:通用定时器2 TIM2_CH2 PWM输出+DMA初始化 *参:arr:自动重装值 说明:定时器溢出时间计算方法:Tout=((arr+1)(psc+1))/Ft us. Ft=定时器工作频率,单位:Mhz */ void PWM_WS2812B_Init(uint16_t arr) { //结构体变量 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; DMA_InitTypeDef DMA_InitStructure; //使能RCC时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能TIM2时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能DMA1时钟 //初始化GPIO口 GPIO_InitStructure.GPIO_Pin = WS2812B_PIN; //GPIO口 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(WS2812B_PORT,&GPIO_InitStructure); //根据指定的参初始化GPIO口 //初始化TIM2 TIM_TimeBaseStructure.TIM_Prescaler=0; //定时器分频:(0+1)=1,不分频 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计模式 TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //根据指定的参初始化TIM2 //初始化TIM2 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 //TIM_OCInitStructure.TIM_Pulse = 0; //待装入捕获比较寄存器的脉冲值(此程序不用加初值) TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根据指定的参初始化外设TIM2 Channel2 /* 此处为知识点所描述处的对应代码,一定要有。移植时注意0C2代表定时器通道2*/ TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器 TIM_Cmd(TIM2, DISABLE); //失能TIM2,防止第一个脉冲异常 TIM_DMACmd(TIM2, TIM_DMA_CC2, ENABLE); //使能TIM2_CH2的DMA功能(CC2对应通道2) DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->CCR2); //设置DMA目的地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Single_LED_Buffer; //设置DMA源地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向:从内存SendBuff到内存ReceiveBuff DMA_InitStructure.DMA_BufferSize = DATA_SIZE; //一次传输大小DMA_BufferSize=SendBuffSize DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //ReceiveBuff地址不增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //SendBuff地址自增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //ReceiveBuff据单位,16bit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //SENDBUFF_SIZE据单位,16bit DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA模式:正常模式(传输一次) DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级:中 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //内存到内存的传输 DMA_Init(DMA1_Channel7, &DMA_InitStructure); //配置DMA1的7通道(不同定时器的通道不一样) DMA_Cmd(DMA1_Channel7, DISABLE); //失能DMA1的7通道,因为一旦使能就开始传输 } //复位带 void WS2812B_Reset(void) { TIM_Cmd(TIM2, DISABLE); WS2812B_LOW; Delay_ms(1); //此处延时时间最小值大于50us即可 } //写据编码 void PWM_WS2812B_Write_24Bits(uint16_t num, uint32_t GRB_Data) { // 参解释变更: // num: 如果为特定值(如0xFFFF),则表示写入所有珠(保持向后兼容) // 否则,num代表要设置的单个珠的索引 // GRB_Data: 要写入的颜色值 uint8_t i; // 判断是设置所有珠还是单个珠 if (num == 0xFFFF) { // 使用一个特殊值表示设置全部珠 for (uint16_t j = 0; j < LED_NUM; j++) { for (i = 0; i < DATA_SIZE; i++) { Single_LED_Buffer[j * DATA_SIZE + i] = ((GRB_Data << i) & 0x800000) ? T1H : T0H; } } } else { // 设置单个珠 if (num >= LED_NUM) return; // 索引检查 for (i = 0; i < DATA_SIZE; i++) { Single_LED_Buffer[num * DATA_SIZE + i] = ((GRB_Data << i) & 0x800000) ? T1H : T0H; } } } //点亮珠 void PWM_WS2812B_Show(uint16_t num) typedef struct { uint16_t breath_step; uint8_t current_color_index; uint32_t current_color; uint8_t breath_direction; // 0:增加亮度, 1:减小亮度 } BreathingState_t; static BreathingState_t breath_state = {0, 0, 0, 0}; void PWM_WS2812B_SetBrightness(uint32_t* grb_color, uint8_t brightness) { if (brightness > MAX_BRIGHTNESS) brightness = MAX_BRIGHTNESS; // 分离GRB分量 uint8_t g = (*grb_color >> 16) & 0xFF; uint8_t r = (*grb_color >> 8) & 0xFF; uint8_t b = *grb_color & 0xFF; // 应用亮度缩放(保持颜色比例) g = (g * brightness) / MAX_BRIGHTNESS; r = (r * brightness) / MAX_BRIGHTNESS; b = (b * brightness) / MAX_BRIGHTNESS; // 重新组合GRB颜色 *grb_color = ((uint32_t)g << 16) | ((uint32_t)r << 8) | b; } void PWM_WS2812B_Breathing_MultiColor(uint16_t start_id, uint16_t end_id, Bst *current, uint8_t color_count, uint16_t speed) { if (start_id >= LED_NUM || end_id >= LED_NUM || start_id > end_id || color_count == 0) return; //static uint16_t breath_step = 0; //static uint8_t current_color_index = 0; uint16_t i; // 计算颜色过渡比例 uint8_t next_color_index = (current->current_color_index + 1) % color_count; OLED_ShowNum(3,1,next_color_index, 2); float transition_ratio = (float)current->breath_step / BREATH_STEP_MAX; // 获取当前和下一个颜色 uint32_t current_grb = current->color_palette[current->current_color_index]; uint32_t next_grb = current->color_palette[next_color_index]; // 分离当前颜色的GRB分量 uint8_t current_g = (current_grb >> 16) & 0xFF; uint8_t current_r = (current_grb >> 8) & 0xFF; uint8_t current_b = current_grb & 0xFF; // 分离下一个颜色的GRB分量 uint8_t next_g = (next_grb >> 16) & 0xFF; uint8_t next_r = (next_grb >> 8) & 0xFF; uint8_t next_b = next_grb & 0xFF; // 线性插值计算过渡颜色 uint8_t final_g = current_g + (uint8_t)((next_g - current_g) * transition_ratio); uint8_t final_r = current_r + (uint8_t)((next_r - current_r) * transition_ratio); uint8_t final_b = current_b + (uint8_t)((next_b - current_b) * transition_ratio); uint32_t final_color = ((uint32_t)final_g << 16) | ((uint32_t)final_r << 8) | final_b; // 应用正弦波亮度变化 float sin_value = sinf(2 * 3.14159f * current->breath_step / BREATH_STEP_MAX); uint8_t brightness = (uint8_t)((sin_value + 1.0f) * 50.0f); PWM_WS2812B_SetBrightness(&final_color, brightness); // 设置珠颜色 for (i = start_id; i <= end_id; i++) { PWM_WS2812B_Write_24Bits(i, final_color); } // 显示更新 // 更新状态 current->breath_step += speed; if (current->breath_step >= BREATH_STEP_MAX) { current->breath_step = 0; current->current_color_index = next_color_index; } } void PWM_WS2812B_BreathingCycle_Segment(uint16_t start_id, uint16_t end_id, uint16_t speed, Bst current) { PWM_WS2812B_Breathing_MultiColor(start_id, end_id, current, current->color_count, speed); } void PWM_WS2812B_Allreset(void) { uint16_t i; for(i = 0; i < LED_NUM; i++) { PWM_WS2812B_Write_24Bits(i, Dead_color);//先让所有熄灭 All_LED_DE[i] = 0;//同时让所有失能 } } /****************************************************************************** @file HDL_WS2812B.h @author huiyang @version V1.0 @date 01/21/2022 ******************************************************************************/ #ifndef _HDL_WS2812B_H #define _HDL_WS2812B_H #include “stm32f10x.h” #define MAX_BRIGHTNESS 100 // 最大亮度百分比 #define BREATH_STEP_MAX 512 // 呼吸步进最大值 #define WS2812B_PIN GPIO_Pin_1 #define WS2812B_PORT GPIOA #define WS2812B_LOW GPIO_ResetBits(WS2812B_PORT,WS2812B_PIN) #define WS2812B_HIGH GPIO_SetBits(WS2812B_PORT,WS2812B_PIN) #define Dead_color 0x000000 #define GREEN 0xFF0000 #define RED 0x00FF00 #define BLUE 0x0000FF #define WHITE 0xFFFFFF /* 根据DataSheet定义0/1编码对应的高电平比较值,因为高电平在前,定义高电平的即可 ** 高低电平的比例约为2:1 */ #define WS2812B_ARR 90 //TIM2的自动重装载值 #define T0H 29 //0编码高电平时间占1/3 #define T1H 58 //1编码高电平时间占2/3 /* 珠亮的个 / #define LED_NUM 100 //底层驱动未用,为应用方便,先加上 #define DATA_SIZE 24 //WS2812B一个编码的bit,38\uint32_t mode1[3] = {0xff00,0x00ff00,0x0000ff};//绿-红-蓝 extern uint32_t mode1[3]; extern uint32_t mode2[3]; extern uint32_t mode3[3]; extern uint32_t mode_red[1]; typedef struct { uint16_t breath_step; uint8_t current_color_index; uint8_t breath_direction; uint32_t* color_palette; uint8_t color_count; } Bst; extern Bst arr[4]; void PWM_WS2812B_Init(uint16_t arr); void WS2812B_Reset(void); void PWM_WS2812B_Write_24Bits(uint16_t num,uint32_t GRB_Data); void PWM_WS2812B_Show(uint16_t num); void PWM_WS2812B_Red(uint16_t num); void PWM_WS2812B_Green(uint16_t num); void PWM_WS2812B_Blue(uint16_t num); void PWM_WS2812B_BreathingCycle_Segment(uint16_t start_id, uint16_t end_id, uint16_t speed, Bst current); void PWM_WS2812B_SetBrightness(uint32_t grb_color, uint8_t brightness); void PWM_WS2812B_Breathing_SingleColor(uint16_t start_id, uint16_t end_id, uint32_t base_color, uint16_t speed); void PWM_WS2812B_Breathing_MultiColor(uint16_t start_id, uint16_t end_id, Bst current, uint8_t color_count, uint16_t speed); void PWM_WS2812B_Allreset(void); #endif 基于以上代码,不要修改已经确定的量,实现控制N个级联的10*10WS2812B板显示波纹的RGB渐变效果,要求能自定义精确控制能以第几个板的某一点或某一中心区域(4个点)为中心的水波纹效果,可以实现多个同时出现的波纹效果
最新发布
11-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值