位运算、递推与递归

简介: 位运算、递推与递归

位运算

1.64位整数乘法

64位整数乘法 (nowcoder.com)

这题就是很简单的龟速乘,因为1e=18*1e18会爆longlong,假如编译器支持可以用__int128_t,或者高精度也行

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qadd(ll a,ll k,ll p)//龟速乘
{
    ll res=0;//加法的零元是0
    while(k)
    {
        if(k&1) res=(res+a)%p;
        a=(a+a)%p;
        k>>=1;
    }
    return res;
}
int main()
{
    ll a,b,p;
    scanf("%lld%lld%lld",&a,&b,&p);
    printf("%lld\n",qadd(a,b,p));
    return 0;
}

递推与递归

1.费解的开关

费解的开关 (nowcoder.com)

这题有多种做法,其中有bfs,或者终止状态递推6步,还有高斯消元的做法,现在让我们看看递推的做法


二进制枚举第一行所有会变到的状态,1表示改变这个位置,0表示不变,然后将第一锁死看第二行,枚举第二行的上一行假如上一行有0,则将这一行的这一位改变一下,这样就使得上一行的0全都变成1了,直到操作到最后一行,看看最后一行是不是全为0即可

1. #in#include<bits/stdc++.h>
using namespace std;
const int N=6;
char str[N][N],temp[N][N];
int dx[6]={-1,0,1,0,0},dy[6]={0,1,0,-1,0};//上 右 下 左 中
void trans(int x,int y)//用来改变一个位置
{
    for(int i=0;i<5;i++)//枚举五个方向
    {
        int tx=x+dx[i],ty=y+dy[i];
        if(tx<0||tx>4||ty<0||ty>4) continue;
        temp[tx][ty]^=1;
    }
}
void solve()
{
    for(int i=0;i<5;i++) scanf("%s",str[i]);
    int ans=7;
    for(int i=0;i<32;i++)
    {
        int cnt=0;
        memcpy(temp,str,sizeof str);
        for(int j=0;j<5;j++)//枚举改第一行的状态
            if(i>>j&1) cnt++,trans(0,j);
        for(int j=0;j<4;j++)//枚举改剩下的几行
          for(int k=0;k<5;k++)
              if(temp[j][k]=='0') cnt++,trans(j+1,k);
        for(int j=0;j<5;j++)//看看最后几行是不是全为1
           if(temp[4][j]=='0') cnt=0x3f3f3f3f;
        ans=min(cnt,ans);
    }
    if(ans<=6) printf("%d\n",ans);//假如小于6了
    else puts("-1");
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--) solve();
    return 0;
}

2.约数之和

97. 约数之和 - AcWing题库

约数之和的公式:


求等比数列也有公式就是p^k-1/p-1

然后这题用递归来做定义sum(p,k)是约数为p,次方是k的前k相等比数列的和

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=9901;
int a,b;
int qmi(int a,int k)
{
    int res=1;
    while(k)
    {
        if(k&1) res=(ll)res*a%mod;
        a=(ll)a*a%mod;
        k>>=1;
    }
    return res;
}
int sum(int p,int k)//用来求sum
{
    if(k==1) return 1;//假如是1了,就返回1
    if(k&1) return (sum(p,k-1)+qmi(p,k-1))%mod;//奇数
    else return ((1+qmi(p,k/2))*sum(p,k/2))%mod;//偶数
}
int main()
{
    int ans=1;
    cin>>a>>b;
    for(int i=2;i<=a/i;i++)//分解质因数
        if(a%i==0)
        {
            int s=0;
            while(a%i==0) s++,a/=i;//获取质因数的个数
            ans=(ll)ans*sum(i,b*s+1)%mod;//按照公式求一遍
        }
    if(a>1) ans=(ll)ans*sum(a,b+1)%mod;//假如最后也是个质因数
    if(a==0) ans=0;
    cout<<ans<<endl;
    return 0;
}

3.分形之城

98. 分形之城 - AcWing题库

这题就是找规律递归到子问题

n层是可以由n-1层得到的,只不过的经过坐标变化,然后在分别求一下坐标变化需要改变的值即可

get(N,A)表示在第N层获取A这个点的坐标,然后距离直接就两点间距离公式即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Piont//用来存坐标
{
    ll x,y;
};
Piont get(ll n,ll a)
{
    if(n==0) return {0,0};//假如0层了,说明只有0,0这一个点
    ll block=1ll<<2*n-2,len=1ll<<n-1;
    auto d=get(n-1,a%block);//处理子问题
    ll x=d.x,y=d.y;
    int z=a/block;
    //图中每种情况
    if(z==0) return {y,x};
    else if(z==1) return {x,y+len};
    else if(z==2) return {x+len,y+len};
    else return {len+len-1-y,len-1-x};
}
void solve()
{
    ll n,a,b;
    scanf("%lld%lld%lld",&n,&a,&b);
    auto da=get(n,a-1),db=get(n,b-1);//获取a,b的坐标,因为数是0开始记的,所以要减1
    double dx=da.x-db.x,dy=da.y-db.y;
    printf("%.0lf\n",sqrt(dx*dx+dy*dy)*10);//输出两点间距离
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--) solve();
    return 0;
}
相关文章
|
6月前
|
算法
算法思想总结:位运算
算法思想总结:位运算
|
6月前
|
测试技术 Windows
【动态规划】【位运算】1787. 使所有区间的异或结果为零
【动态规划】【位运算】1787. 使所有区间的异或结果为零
|
12月前
|
算法 C++
C++快速幂(递归)
C++快速幂(递归)
|
6月前
递归阶乘详解
递归阶乘详解
39 1
|
6月前
面试题 08.05:递归乘法
面试题 08.05:递归乘法
38 0
|
算法
双指针算法、位运算
双指针算法、位运算
67 0
|
机器学习/深度学习
求n的阶乘(递归法和循环法
根据阶乘的计算方法:n!= 1 * 2 * 3*…*n,我们在一个for循环完成 n 次乘法运算。注意因为是连乘,最终阶乘结果可能会非常大所以我们在Fac函数中用 long long 类型的变量来记录阶乘的结果。
|
算法
【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)
【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)
【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)
|
机器学习/深度学习 算法
斐波拉契数列的递推递归求解算法
斐波拉契数列的递推递归求解算法
107 0
|
机器学习/深度学习 BI
372. 超级次方 : 递归快速幂应用题
372. 超级次方 : 递归快速幂应用题