hdu 4317 Unfair Nim(数位DP,4级)

本文深入探讨了游戏开发领域的关键技术,包括游戏引擎、编程语言、硬件优化等,同时着重介绍了AI音视频处理的应用场景和实现方法,如语义识别、物体检测、语音变声等。通过实例分析,揭示了技术融合带来的创新解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Unfair Nim

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 662    Accepted Submission(s): 271


Problem Description
Alice and Bob are tired of playing the Nim game, because they are so clever that before the beginning of the game, they have already known the result. Here is their conversation:

Bob: It's unfair. I am always the second player, but you know, if the number of stones in each pile are distributed uniformly, at most time the first player, i.e., you, will win.
Alice: Yes, I agree with you. So I give you a chance to beat me, you are allowed to add some stones in some piles (but you can't create a new pile) before the game starts, so that you can win as the second player.
Bob: Yeah, that's cool. I will win definitely.
Alice: But note, you must add the minimum of the stones. If you add more stones than necessary to win, your winning will be cancelled.
Bob: er... Let me see...

For the readers who are not familiar with the Nim game (from Wikipedia):
Nim is a mathematical game of strategy in which two players take turns removing stones from distinct heaps. On each turn, a player must remove at least one stone, and may remove any number of stones provided they all come from the same heap. The player who take the last stone wins.
 

Input
The first line of each test case contains an integer N (1 <= N <= 10), the number of piles at the beginning. The next line contains N positive integers, indicating the number of stones in each pile. The number of stones in each pile is no more than 1,000,000.
 

Output
Output one line for each test case, indicating the minimum number of stones to add. If it is impossible, just output "impossible".
 

Sample Input
  
3 1 2 3 3 1 1 1 1 10
 

Sample Output
  
0 3 impossible
 

Author
TJU
 

Source
 

Recommend
zhuyuanchen520

思路:dp[x][y],从右向左数,第x位1是偶数状态下的进位状态y.然后就是判断各种条件了。


我们的DP就是从右边到左边来做的,首先保存每一列的状态,也是用二进制来表示的,如  7,5,0,0(假设右边是低位)

那么我们设 f[ i ][ j ]表示右边起第 i 位 保证这一列的 1 的个数是偶数的情况下,进位的状态为 j (进位的状态与上面的每列状态一样,就是每个数产生进位的状态)

那么有 f[ i ][ j ]=min{ f[ i-1][ k ]+满足进位后这一列的1 的个数为偶数,并且进位状态为1 需要加的数的和}

具体的一堆判断用位运算来做,

     tmp=s[ i ]&k表示第i列一定产生的进位   

     s[ i ]^k 表示加上之前的进位后这一列的状态 

     j^tmp表示需要再进位的是哪几位

     s[ i ]^k  &   j^tmp ==    j^tmp 只有满足需要进的位都为1 才能成功进位(如果为0 ,加1 后还不能进位,加2 的情况可以转换成高一位的计算)

     s[ i ]^k  ^   j^tmp 表示满足进位后的状态,这个状态必须满足 1 的个数为偶数,如果为 奇数并且个数少于n ,则再加随便再0的位置加个1就行,不过答案要多加一次

摘自 fp_hzq


注意:凡是带&等操作的,都需要加括号,(就这,调了进一个钟头,饭都没吃。。。。)


#include<iostream>
#include<cstring>
#include<cstdio>
#define gb(x) (1<<x)
using namespace std;
const int mm=1<<11;
int dp[25][mm],s[25],bit[mm],f[25];
int n;
int getbit(int x)
{
    int ret=0;
    while(x)
    {
        ret+=x&1;
        x>>=1;
    }
    return ret;
}
int main()
{
    for(int i=0; i<mm; ++i)
        bit[i]=getbit(i);
    while(~scanf("%d",&n))
    {
        for(int i=0; i<n; ++i)
            scanf("%d",&f[i]);
        if(n<2)
        {
            puts("impossible");
            continue;
        }
        int m;
        memset(s,0,sizeof(s));
        for(int i=1; i<25; ++i)
        {
            for(int j=0; j<n; ++j)
                if(f[j]&gb(i-1))
                    s[i]|=gb(j);
            if(s[i])m=i+1;
        }
        memset(dp,0x3f,sizeof(dp));
        int ans=dp[0][0];
        dp[0][0]=0;
        int tmp;
        for(int i=1; i<=m; ++i)
            for(int j=0; j<gb(n); ++j)
                if(dp[i-1][j]<ans)
                {
                    tmp=j&s[i];///已产生的进位
                    for(int k=tmp; k<gb(n); ++k) ///k 进位状态
                    {
                        if(((k&tmp)==tmp)&&///包含已产生的
                                ((s[i]^j)&(tmp^k))==(tmp^k)&&///和需要包括进位
                                ((bit[s[i]^j^tmp^k]&1)==0||bit[s[i]^j^tmp^k]<n)/// 需要加上 tmp^k
                          )
                        {
                            ///if(k==0)puts("www");
                            int z=bit[tmp^k]+(bit[s[i]^j^tmp^k]&1);
                            dp[i][k]=std::min(dp[i][k],dp[i-1][j]+(bit[tmp^k]+(bit[s[i]^j^tmp^k]&1))*gb(i-1));
                            ///cout<<dp[i][k]<<" i k "<<i<<" "<<k<<" "<<j<<" "<<z<<" "<<tmp<<endl;
                        }
                    }
                }
        for(int i=0; i<gb(n); ++i)
            if((bit[i]&1)==0)
            {
                ans=std::min(ans,dp[m][i]);
            }
        printf("%d\n",ans);
    }
}




内容概要:本文详细介绍了如何使用STM32微控制器精确控制步进电机,涵盖了从原理到代码实现的全过程。首先,解释了步进电机的工作原理,包括定子、转子的构造及其通过脉冲信号控制转动的方式。接着,介绍了STM32的基本原理及其通过GPIO端口输出控制信号,配合驱动器芯片放大信号以驱动电机运转的方法。文中还详细描述了硬件搭建步骤,包括所需硬件的选择与连接方法。随后提供了基础控制代码示例,演示了如何通过定义控制引脚、编写延时函数和控制电机转动函数来实现步进电机的基本控制。最后,探讨了进阶优化技术,如定时器中断控制、S形或梯形加减速曲线、微步控制及DMA传输等,以提升电机运行的平稳性和精度。 适合人群:具有嵌入式系统基础知识,特别是对STM32和步进电机有一定了解的研发人员和技术爱好者。 使用场景及目标:①学习步进电机与STM32的工作原理及二者结合的具体实现方法;②掌握硬件连接技巧,确保各组件间正确通信;③理解并实践基础控制代码,实现步进电机的基本控制;④通过进阶优化技术的应用,提高电机控制性能,实现更精细和平稳的运动控制。 阅读建议:本文不仅提供了详细的理论讲解,还附带了完整的代码示例,建议读者在学习过程中动手实践,结合实际硬件进行调试,以便更好地理解和掌握步进电机的控制原理和技术细节。同时,对于进阶优化部分,可根据自身需求选择性学习,逐步提升对复杂控制系统的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值