CSDN竞赛第37期,题三

题目名称:大整数替换数位

题意:以字符串的形式给你一个长度为 M 的整数 N,请你计算出对这个数进行一次操作后模 9 的值为 1 的所有可能的不同操作 方式。 在一次操作中, 我们可以选择 N 的一个数位 N[i],并把它替换成另一个不同的 0 9 范围之内的数 B,当且仅当它们选 择的 i B 不同时两种操作方式不同。

此题由CSDN用户a23333a提供 

输入:第一行包含一个整数M(1<=M<=100000)。第二行包含一个大整数N。

输出:第一行输出一个整数,代表对N执行一次操作后使N模9的值为1的所有可能的不同操作方式数量。

输入示例:

4

2345     

输出示例:

示例提示:一共有5种不同的操作方式使操作后的数模9=1。

前两种是:

i=0,B=7,即2变为7,2345->7345,7345%9=1;

i=1,B=8,即3变为8,2345->2845,2845%9=1。

题意分析:

简单来说,就是在字符串形式的整数N[i]中,选择一位数字进行替换(替换成0~9中一个与原来相异的数),使得替换以后的整数模9的结果为1。

已知能被9整除的数字:各个位上的数字之和能被9整除。

那么模9的结果为1,也就是各个位置上数字之和模9后为1。

因此主要思路就是对整数各位置上的数字求和,然后判断模9的结果。

模9的结果分为以下三种:1,0,2~8。

CASE1:

模9后结果为1:

直接满足题目要求,因此替换的数字必须刚好和原来相差9,满足条件的数字只有0和9:

用num(m)指代m出现的次数,故有num(0)+num(9)种替换方式。

CASE2:

模9后结果为0:

为了满足题目要求,需要选择一个数字进行替换,有两种满足替换的方法:

①:将某个数字替换成比原来大1的数;

②:将某个数字替换成比原来小8的数。

特别的,对于数字8而言,既可以+1,也可以-8。而其他的数字,或+1,或-8。

也就是说,8有两个可替换数,其他数字只有一个可替换数。用num(8)指代8的个数,因此共有M+num(8)种替换方式。

CASE3:

模9后结果为2~8:

假设模9后结果为s,为了满足题目要求,需要将s降至1,或升至10(对于只替换单个数字而言,只有这两种可能),设某一位置上数字为m

①:将s降至1,即m替换以后s为1,m需要替换成比自身小s-1的数(因为此时模9后的s与1差了s-1,将某位上的m减小s-1就能满足s为1),但替换后的数字不能为负数,所以需要满足不等式m-(s-1)>=0,即m>=s-1

②:将s升至10,即m替换以后s为10,同理,m需要替换成比自身大10-s的数,替换后的数字只能是一位数,所以满足m+(10-s)<=9,即m<=s-1

由此可见,m取0~9的任何一位,都存在一个可替换数,特别的,当m为s-1时,有两个可替换数。综上,共有M+num(s-1)种替换方式。

其实,CASE2和CASE3在思路上可归为同一类情况,CASE2中模9的结果为0,也就是9,将CASE3中的s代入9也可以。但实际的模运算不存在9,因此为了便于操作,分为两种情况。

#include<iostream>
using namespace std;
int main() {
    int M, s=0, num=0;
    char N[100001];
    cin>>M;
    for(int i=0;i<M;i++){
        cin>>N[i];
        s+=N[i]-'0';//累加 
        s%=9;//(a+b+...)%n=(a%n+b%n+...)%n 
    }
    //CASE1
    if(s==1){
        for(int i=0;i<M;i++)
            if(N[i]-'0'==0||N[i]-'0'==9) num++;
    }
    //CASE2
    else if(s==0){
        for(int i=0;i<M;i++)
            if(N[i]-'0'==8) num++;
        num+=M;
    }
    //CASE3
    else{
        for(int i=0;i<M;i++){
        	if(N[i]-'0'==s-1)
        		num++;
        }
        num+=M;
    }
    cout<<num;
    return 0;
}

“不积跬步,无以至千里;不积小流,无以成江海。” ————荀子

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值