模拟算法学习笔记

1. 打表与周期性问题

题目直通车

这是一道模拟题,表中给出了输赢关系,虽然狂打if和switch都可以,但是我们可以用一种更为简洁的方式进行判断,那就是——打表

我们可以开设一个数组用来存储这张表中的输赢关系,假设$0$为平,$-1$为输,$1$为赢:

short game[6][6]={{0,-1,1,1,-1},{1,0,-1,1,-1},{-1,1,0,-1,1},{-1,-1,1,0,1},{1,1,-1,-1,0}};

那么,访问输赢关系就是——

game[a[i%na]][b[i%nb]]==1

其中,$i$为循环变量,$N_a$为小A周期长度,$N_b$为小B周期长度。这里便是周期性问题的一个解法——$mod$

这种方式使在接触大数据范围时不用涉及高精度。

整体代码如下:

#include <iostream>
using namespace std;
short game[6][6]={{0,-1,1,1,-1},{1,0,-1,1,-1},{-1,1,0,-1,1},{-1,-1,1,0,1},{1,1,-1,-1,0}};
int a[210];
int b[210];
int main()
{
    int n,na,nb;
    cin>>n>>na>>nb;
    int as=0,bs=0;
    for (int i=0;i<na;i++)
    {
        cin>>a[i];        
    }
    for (int i=0;i<nb;i++)
    {
        cin>>b[i];
    }
    for (int i=0;i<n;i++)
    {
        if (game[a[i%na]][b[i%nb]]==1)
        {
            ++as;
        }
        else if (game[a[i%na]][b[i%nb]]==-1)
        {
            ++bs;
        }
    }
    cout<<as<<" "<<bs<<endl;
    return 0;
}

2. 数组操作

题目直通车

这道题需要使用二维数组,难点在于旋转——

  • 顺时针:
void c(int a,int b,int n)
{
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            h[a+j-1][b+n-i]=g[a+i-1][b+j-1];
        }
    }
    for (int i=a;i<=a+n-1;i++)
    {
        for (int j=b;j<=b+n-1;j++)
        {
            g[i][j]=h[i][j];
        }
    }
}
  • 逆时针:
void d(int a,int b,int n)
{
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            h[a+n-j][b+i-1]=g[a+i-1][b+j-1];
        }
    }
    for (int i=a;i<=a+n-1;i++)
    {
        for (int j=b;j<=b+n-1;j++)
        {
            g[i][j]=h[i][j];
        }
    }
}

最重要的是这两个公式:

h[a+j-1][b+n-i]=g[a+i-1][b+j-1];


h[a+n-j][b+i-1]=g[a+i-1][b+j-1];

这两个公式把$g$数组的数据拷贝到$h$旋转。

主函数里需要确定小矩阵的起始和大小,因此有如下的代码:

int a=x-r,b=y-r,k=2*r+1;

代码如下:

#include <iostream>
using namespace std;
int g[510][510];
int h[510][510];
void c(int a,int b,int n)
{
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            h[a+j-1][b+n-i]=g[a+i-1][b+j-1];
        }
    }
    for (int i=a;i<=a+n-1;i++)
    {
        for (int j=b;j<=b+n-1;j++)
        {
            g[i][j]=h[i][j];
        }
    }
}
void d(int a,int b,int n)
{
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            h[a+n-j][b+i-1]=g[a+i-1][b+j-1];
        }
    }
    for (int i=a;i<=a+n-1;i++)
    {
        for (int j=b;j<=b+n-1;j++)
        {
            g[i][j]=h[i][j];
        }
    }
}
int main()
{
    int n,m;
    cin>>n>>m;
    int cnt=0;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            g[i][j]=++cnt;
        }
    }
    while (m--)
    {
        int x,y,r,z;
        cin>>x>>y>>r>>z;
        int a=x-r,b=y-r,k=2*r+1;
        if (z==0)
        {
            c(a,b,k);
        }
        else
        {
            d(a,b,k);
        }
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            cout<<g[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

3. 高精度

高精度加法

高精度减法

高精度乘法之大乘小

高精度乘法之大乘大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值