2018 ACM-ICPC 中国大学生程序设计竞赛线上赛

B Goldbach

B题的大意是,有T组测试数据,给一个偶数然后输出它分解的两个素数之和,可以是任意两个满足的素数。

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <algorithm>  
#include <iostream>  
#include <math.h>  

using namespace std;
const int Times = 10;
typedef unsigned long long LL;
// a * b % n  
//例如: b = 1011101那么  
//a * b mod n = (a * 1000000 mod n + a * 10000 mod n + a * 1000 mod n + a * 100 mod n + a * 1 mod n) mod n  
LL multi(LL a, LL b, LL m)    // 计算 a*b % m  
{
    LL ans = 0;
    a %= m;
    while (b)
    {
        if (b & 1)
        {
            ans = (ans + a) % m;
            b--;
        }
        b >>= 1;
        a = (a + a) % m;
    }
    return ans;
}

LL quick_mod(LL a, LL b, LL m)  // 计算 a^b % m  
{
    LL ans = 1;
    a %= m;
    while (b)
    {
        if (b & 1)
        {
            ans = multi(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi(a, a, m);
    }
    return ans;
}

bool Miller_Rabin(LL n)
{
    if (n == 2) return true;
    if (n < 2 || !(n & 1)) return false;
    LL m = n - 1;
    int k = 0;
    while ((m & 1) == 0)
    {
        k++;
        m >>= 1;
    }
    for (int i = 0; i<Times; i++)
    {
        LL a = rand() % (n - 1) + 1;
        LL x = quick_mod(a, m, n);     //大整数的快速幂算法( (a*a)% n),直接a*a发送数据溢出=>(a%n * a%n)%n  
        LL y = 0;
        for (int j = 0; j<k; j++)
        {
            y = multi(x, x, n);
            if (y == 1 && x != 1 && x != n - 1) return false;
            x = y;
        }
        if (y != 1) return false;
    }
    return true;
}

int main()
{
    int T; long long i;
    scanf_s("%d", &T);
    while (T--)
    {
        LL n;
        scanf_s("%llu", &n);
        for (i = 3; i < n; i=i+2) //如果i从2开始每次加1的话,会超时
            if (Miller_Rabin(i) && Miller_Rabin(n - i))
            {
                printf("%lld %lld\n", i, n - i);
                break;
            }
    }
    return 0;
}

I Reversion Count

题目大意是:有一个正整数X,X的返回计数为Y.例如,X = 123,Y = 321; X = 1234,Y = 4321。 Z =(XY)/ 9,如果Z仅由一个数字(0,1,2 … 9)组成,如Z = 11,Z = 111,Z = 222,(不考虑’+’和’ - ‘)则输出“YES”,否则输出“NO”

//直接套用大数减法,大数除法模板
#include<stdio.h>
#include<string.h>
#include <iostream>
using namespace std;
#define MAX 1000    
int Subtraction(char num1[], char num2[], int sum[])
{
    int i, j, len, blag;
    char *temp;
    int n2[MAX] = { 0 };
    int len1 = strlen(num1); // 计算数组num1的长度,即大数的位数 
    int len2 = strlen(num2); // 计算数组num2的长度,即大数的位数

                             // 在进行减法之前要进行一些预处理 
    blag = 0; // 为0表示结果是正整数,为1表示结果是负整数 
    if (len1 < len2) // 如果被减数位数小于减数
    {
        blag = 1; // 标记结果为负数
                  // 交换两个数,便于计算 
        temp = num1;
        num1 = num2;
        num2 = temp;
        len = len1;
        len1 = len2;
        len2 = len;
    }
    else if (len1 == len2) // 如果被减数的位数等于减数的位数
    {
        // 判断哪个数大 
        for (i = 0; i < len1; i++)
        {
            if (num1[i] == num2[i])
                continue;
            if (num1[i] > num2[i])
            {
                blag = 0; // 标记结果为正数 
                break;
            }
            else
            {
                blag = 1; // 标记结果为负数 
                          // 交换两个数,便于计算 
                temp = num1;
                num1 = num2;
                num2 = temp;
                break;
            }
        }
    }
    len = len1>len2 ? len1 : len2; // 获取较大的位数
                                   //将num1字符数组的数字转换为整型数且逆向保存在整型数组sum中,即低位在前,高位在后
    for (i = len1 - 1, j = 0; i >= 0; i--, j++)
        sum[j] = num1[i] - '0';
    // 转换第二个数 
    for (i = len2 - 1, j = 0; i >= 0; i--, j++)
        n2[j] = num2[i] - '0';
    // 将两个大数相减 
    for (i = 0; i <= len; i++)
    {
        sum[i] = sum[i] - n2[i]; // 两个数从低位开始相减 
        if (sum[i] < 0)   // 判断是否有借位 
        {    // 借位 
            sum[i] += 10;
            sum[i + 1]--;
        }
    }
    // 计算结果长度 
    for (i = len1 - 1; i >= 0 && sum[i] == 0; i--)
        ;
    len = i + 1;
    if (blag == 1)
    {
        sum[len] = -1;  // 在高位添加一个-1表示负数 
        len++;
    }
    return len;   // 返回结果的位数 
}

int SubStract(int *p1, int len1, int *p2, int len2)
{
    int i;
    if (len1 < len2)
        return -1;
    if (len1 == len2)
    {                        // 判断p1 > p2
        for (i = len1 - 1; i >= 0; i--)
        {
            if (p1[i] > p2[i])   // 若大,则满足条件,可做减法
                break;
            else if (p1[i] < p2[i]) // 否则返回-1
                return -1;
        }
    }
    for (i = 0; i <= len1 - 1; i++)  // 从低位开始做减法
    {
        p1[i] -= p2[i];         // 相减 
        if (p1[i] < 0)           // 若是否需要借位
        {   // 借位 
            p1[i] += 10;
            p1[i + 1]--;
        }
    }
    for (i = len1 - 1; i >= 0; i--)  // 查找结果的最高位
    {
        if (p1[i])             //最高位第一个不为0
            return (i + 1);       //得到位数并返回
    }
    return 0;                   //两数相等的时候返回0
}

int Division(char num1[], char num2[], char sum[])
{
    int k, i, j;
    int len1, len2, len = 0;     //大数位数
    int dValue;                //两大数相差位数
    int nTemp;                 //Subtract函数返回值
    int num_a[MAX] = { 0 };      //被除数
    int num_b[MAX] = { 0 };      //除数
    int num_c[MAX] = { 0 };      //商 

    len1 = strlen(num1);       //获得大数的位数
    len2 = strlen(num2);

    //将数字字符转换成整型数,且翻转保存在整型数组中 
    for (j = 0, i = len1 - 1; i >= 0; j++, i--)
        num_a[j] = num1[i] - '0';
    for (j = 0, i = len2 - 1; i >= 0; j++, i--)
        num_b[j] = num2[i] - '0';

    if (len1 < len2)          //如果被除数小于除数,直接返回-1,表示结果为0
    {
        return -1;
    }
    dValue = len1 - len2;      //相差位数
    for (i = len1 - 1; i >= 0; i--)    //将除数扩大,使得除数和被除数位数相等
    {
        if (i >= dValue)
            num_b[i] = num_b[i - dValue];
        else                         //低位置0
            num_b[i] = 0;
    }
    len2 = len1;
    for (j = 0; j <= dValue; j++)    //重复调用,同时记录减成功的次数,即为商
    {
        while ((nTemp = SubStract(num_a, len1, num_b + j, len2 - j)) >= 0)
        {
            len1 = nTemp;            //结果长度
            num_c[dValue - j]++;       //每成功减一次,将商的相应位加1
        }
    }
    // 计算商的位数,并将商放在sum字符数组中 
    for (i = MAX - 1; num_c[i] == 0 && i >= 0; i--);  //跳过高位0,获取商的位数 
    if (i >= 0)
        len = i + 1; // 保存位数 
    for (j = 0; i >= 0; i--, j++)     // 将结果复制到sum数组中 
        sum[j] = num_c[i] + '0';
    sum[j] = '\0';   // sum字符数组结尾置0 
    return len;      // 返回商的位数 
}

int main()
{
    int i, len;
    int sum[MAX] = { 0 }; // 存放计算的结果,低位在前,高位在后,即sum[0]是低位 
    char num1[100];
    char num2[100];
    while (cin >> num1) {
        strcpy_s(num2, num1);
        int x = strlen(num1);
        for (int i = 0; i < x; i++)
            num2[i] = num1[x - i-1];
        //_strrev(num2);
        len = Subtraction(num1, num2, sum);    // 两数相减 

        if (sum[i = len - 1] < 0) // 根据高位是否是-1判断是否是负数
        { 
            i--;
        }
        if (sum[i] <= 0) {   //相减结果为0直接输出
            cout << "YES" << endl;
            continue;
        }
        for (int j = 0; i >= 0; i--, j++) {

            num1[j] = sum[i] + '0';
        }

        char sum2[MAX] = { 0 };
        char num3[100] = { '9' };
        len = Division(num1, num3, sum2);
        int flag = 0;
        for (int i = 0; i < len - 1 && len>2; i++) {
            if ((sum2[i] - '0') != (sum2[i + 1] - '0'))
            {
                cout << "NO" << endl;
                flag = 1;
                break;
            }
        }
        if (flag) continue;
        cout << "YES" << endl;
    }
    return 0;
}

L. Nise-Anti-AK Problem

//题目大意是求那个数的f(x)最大,发现直接排序找最大数即可
#include <iostream>
#include <algorithm>
using namespace std;
int n,T;
int a[1001];
int main(){
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        sort(a,a+n);
        cout<<a[n-1]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值