P1010 幂次方 P1022 计算器的改良

P1010 幂次方

一、题目

https://www.luogu.org/problemnew/show/P1010

二、代码

#include<bits/stdc++.h>
using namespace std;

// 根据2的几次幂进行分解
string decompose(int num)
{
    if(num==0)
    {
        return "0";
    }

    string s = "";
    int exp = 0;  // 指数,比如2=2^1,则指数为1
    do
    {
        if(num & 1) // 判断奇数
        {
            // num=2时,exp==1才为真
            string tmp1 = exp==1 ? "2" : "2("+decompose(exp)+")";
            string tmp2 = s=="" ? "" : "+";

            // 拼接字符串,依题意,要把低次方接在后面
            s = tmp1 + tmp2 + s;
        }

        exp++;
    } while(num >>= 1);//每次向右移一位,即除以2

    return s;
}

int main()
{
    int x;
    cin>>x;
    cout<<decompose(x)<<endl;
    return 0;
}
View Code

P1022 计算器的改良

一、题目

https://www.luogu.org/problemnew/show/P1022

二、代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int coe = 0;         // coe * x = value, coe即为x的系数
    int value = 0;
    int pos = -1;       // 数值位于等号左边的数为负(移到右边即为正),位于等号右边的数为正
    char c = getchar();
    int num = 0;        // 当前读入的数值
    int sign = 1;       // 当前数值符号,
    char x;             // 未知数,26个小写字母之一

    while(true)
    {
        if (c>='a' && c<='z')
        {
            x = c;
            if (num == 0)
            {
                // 系数为1
                coe += -pos * sign;

            }
            else
            {
                coe += -pos * sign * num;   //系数左边为正,右边为负,所以pos要取负
            }

            num = 0;
            sign = 1;
        }
        else if (c == '-')
        {
            value += pos * sign * num;
            num = 0;
            sign = -1;
        }
        else if (c == '+')
        {
            value += pos * sign * num;
            num = 0;
            sign = 1;
        }
        else if (c >= '0' && c <= '9')
        {
            num = num * 10 + c - '0';
        }
        else if (c == '=')
        {
            value += pos * sign * num;
            num = 0;
            sign = 1;
            pos = -pos;     //等号右边pos为正
        }
        else   // 换行的时候,要把最后的数(如果有)累加到valu
        {
            value += pos * sign * num;
            break;
        }

        c = getchar();
    }

    double ans = double(value) / coe;//计算ans

    printf("%c=%.3f", x, ans == 0 ? abs(ans) : ans);//这涉及一个很坑的地方:C++里0除以一个负数值为-0,专门避免这种情况

    return 0;
}
View Code

UVA524 素数环

一、题目

https://www.luogu.org/problemnew/show/UVA524

二、分析

例1:以n = 4为例。n = 4的排列有

1,2,3,4    相邻两个数相加都是素数,符合题意
1,2,4,3    2和4相加不是素数,不符合题意
1,3,2,4    2和4相加不是素数,不符合题意
1,3,4,2    4和2相加不是素数,不符合题意
1,4,2,3    4和2相加不是素数,不符合题意
1,4,3,2    相邻两个数相加都是素数,符合题意。

所以正确的答案为

1,2,3,4
1,4,3,2

例2:以n = 5为例。n = 5的排列有

1,2,3,4,5   4和5相加不是素数,不符合题意
1,2,3,5,?    3和5相加不是素数,不符合题意
1,2,4,?    2和4相加不是素数,不符合题意
1,2,5,3,?    5和3相加不是素数,不符合题意
1,2,5,4,?    5和4相加不是素数,不符合题意
1,3,?          1和3相加不是素数,不符合题意
1,4,2,?       4和2相加不是素数,不符合题意
1,4,3,2,5    5和1相加不是素数,不符合题意
1,4,3,5,?    3和5相加不是素数,不符合题意
1,4,5,?       4和5相加不是素数,不符合题意
1,5,?          1和5相加不是素数,不符合题意

所以n=5时,没有答案。

三、代码

#include<bits/stdc++.h>
using namespace std;

int n;
int a[100];
int prime[100];
bool visited[100]; //visited[num]用来标记num是否被使用了

// pos为数组下标
void dfs(int pos)
{
    // num为数组中的数
    for(int num=2; num<=n; num++)
    {
        // 如果这个数已经使用,则不能再用
        if(visited[num])
        {
            continue;
        }

        if(prime[a[pos-1] + num])   //当前数num与上一个数的和为素数
        {
            visited[num] = true;    // 标记
            a[pos] = num;           // 存储,后面需要打印出来
            if(pos == n)            // 放完了n个数
            {
                if(prime[a[pos] + 1]) //这是一个环,所以要计算最后一个数与第一个数1的和
                {
                    for(int j = 1; j < n; j++)
                    {
                        printf("%d ",a[j]);
                    }
                    printf("%d\n", a[n]);  //这里很恶心,行末不能有空格
                }
            }
            else
            {
                dfs(pos + 1);
            }

            visited[num] = false;  //回溯
        }
    }
}

int main()
{
    // 素数打表
    prime[2]=prime[3]=prime[5]=prime[7]=prime[11]=prime[13]=prime[17]=prime[19]=prime[23]=prime[29]=prime[31]=true;     //先处理一下素数

    int cnt = 0;    // 输出的第几组数据
    while(scanf("%d",&n) == 1)
    {
        cnt++;
        printf("Case %d:\n",cnt);
        a[1] = 1;   //第一个数是1
        visited[1] = true; // 这一句可写可不写,因为1就是第一个数
        dfs(2);     //从第二个数开始搜

        cout << endl;
    }
    
    return 0;
}
View Code

P4326 求圆的面积

一、题目

https://www.luogu.org/problemnew/show/P4326

二、分析

COCI是Crotian Open Competition in Informatics, 即克罗地亚信息学公开赛。
本题的坑点在于有些人不知道所谓的出租车几何下的“圆”其实是一个正方形:

 
 

上面这个“圆”中,中心点到边上的任意一点的距离都为|x1 - x2| + |y1 - y2| = 4。

这个“圆”是由上下两个三角形组成的,每个三角形的面积为2r * r / = r * r,所以“圆”的面积为2 * r * r。

#include <iostream>
#include <cstdio>
using namespace std;

const double pi = 3.141592653589793;

int main()
{
    double r;
    cin >> r;
    printf("%.6f\n", pi * r * r);
    printf("%.6f\n", 2 * r * r);

    return 0;
}
View Code

P1009 阶乘之和

#include<iostream>
using namespace std;

int a[2000];
int c[2000];
const int maxDigit=1000; //最大位数,调试时可设n=4,maxDigit=3

// 阶乘相加
void add(int *a,int *c)
{
    int carry = 0;
    // 比如1!+2!+3!+4!
    // i=1时,c[1]=1!=1
    // i=2时,c[1]=1+2!=3
    // i=3时,c[1]=3+3!=9
    // i=4时,c[1]=9+4=13,carry=1,c[1]=3,c[2]=c[2]+a[2]+carry=0+2+1=3
    for(int i = 1; i <= maxDigit; i++)
    {
        c[i] += (a[i] + carry);
        carry = c[i]/10;
        c[i] %= 10;
    }
}

//求阶乘
void fact(int *a,int num)
{
    int carry = 0; // 进位
    for(int i=1; i <= maxDigit; i++)
    {
        // 从高位往低位存储数据,比如5!=120,则a[4]=a[5]=...=0,a[3]=1,a[2]=2,a[1]=0
        a[i] = a[i] * num + carry;
        carry = a[i] / 10;
        a[i] %= 10;
    }
}

int main()
{
    int n;
    cin >> n;
    a[1] = 1;
    for(int i=1;i<=n;i++)
    {
        fact(a, i);
        add(a, c);
    }

    bool flag = false; // 当碰到第一个非0时,更新为true
    for(int i = 1000; i >= 1; i--)
    {
        // 左边的0不要打印出来,从第一个非0数字开始打印
        // 比如000……000120,打印出120
        if(c[i] != 0)
        {
            flag = true;
        }

        if(flag)
        {
            cout << c[i];
        }
    }

    return 0;
}
View Code

P1007 独木桥

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
    int n,l,p,maxT=0,minT=0;
    scanf("%d%d",&l,&n);

    for(int i=1;i<=n;i++)
    {
        scanf("%d",&p);
        maxT=max(maxT,max(l+1-p,p));
        minT=max(minT,min(l+1-p,p));
    }

    printf("%d %d",minT,maxT);

    return 0;
}
View Code

P1002 过河卒

#include<iostream>
using namespace std;

long long a[30][30]={0},n,m,my,mx;

int main()
{
    cin >> n >> m >> my >> mx;//输入数据

    // 整个棋盘往右往下挪两格,这样马处于原点(挪移后
    // 变成(2,2)点,往左上方跳不会出现数组越界的情况
    n += 2; // n行
    m += 2; // m列
    my += 2;// 马位于第几行
    mx += 2;// 马处于第几列

    for(int r = 2; r <= n; r++) // 共有n+1行
    {
        for(int c = 2; c <= m; c++) // 共有m+1列
        {
            a[r][c] = a[r - 1][c] + a[r][c - 1]; // 左侧的数 + 上方的数
            a[2][2]=1;  // 要初始化为1,若为0后面全是0

            // 马的9个控制点
            a[my][mx]=0;// 马本身的位置
            a[my + 2][mx + 1]=0;
            a[my + 2][mx - 1]=0;
            a[my - 2][mx + 1]=0;
            a[my - 2][mx - 1]=0;
            a[my + 1][mx + 2]=0;
            a[my + 1][mx - 2]=0;
            a[my - 1][mx + 2]=0;
            a[my - 1][mx - 2]=0;
        }
    }

    cout <<a[n][m];

    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/alan-blog-TsingHua/p/10865507.html