1049. Counting Ones (30) 从1到n整数中1出现的次数

本文提供了一种高效算法来解决PAT题目中关于数字中1的个数的问题,并通过C++代码实现了解决方案。该算法考虑了数字的每一位,计算从1到给定数字n中所有数字中1出现的次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指offer,leetcode,PAT

转载地址(下面的博文讲解的很清楚,容易明白)
http://blog.youkuaiyun.com/yi_afly/article/details/52012593

这里写图片描述

PAT题目联系
https://www.patest.cn/contests/pat-a-practise/1049
ac代码

#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <sstream>
#include <list>
#include <stack> 
#include <map> 
#include <set> 

using namespace std;

#define INF 0x7fffffff

const int N = 505;

int main()
{
  //freopen("in.txt", "r", stdin);
  int n;
  while(scanf("%d", &n) != EOF)
  {
    if(n<1)
    {
      printf("0\n");
      continue;
    }

    int base = 1;

    int count = 0;

    int round = n;
    while(round > 0) // 依次遍历 每一位的数字
    {
      int weight = round%10; // 当前位的值

      round/=10; // 去除当前位,前面的数字值

      count += round*base;

      /**
       * 比如 514 ,十位是1
            10个数: 010 011 012 ... 019
            10个数: 110 111 112 ... 119
            10个数: 210 211 212 ...
            ...
            10个数: 410 411 ...
            5个数: 510 511 512 513 514, 最后一轮需要看个位数是多少了
       */
      if(weight == 1) // 当前位的值就是1,需要看当前位后面的数是多少
      {  
        count += (n%base) + 1;
      }
      else if(weight > 1) // 当前位值大于1 那么最后一轮还是base个数
      {
        count += base;
      }

      base*=10;
    }

    printf("%d\n", count);
  }
  return 0;
}
# T617559 「TPOI-5A」Luminescence ## 题目背景 ![](https://cdn.luogu.com.cn/upload/image_hosting/ownsj515.png) (图片来自 Phigros 曲绘,侵删。) ## 题目描述 给定 $n$ 与两个长度为 $n$ 的序列 $a,b$。定义一个 $0\sim n-1$ 的排列 $q$ 是 **魔怔的**,当且仅当: - $\forall 1\le k\le n,\min^k_{i=1}q_i=a_k$。 - $\forall 1\le k\le n,\min^n_{i=k}q_i=b_k$。 定义一个排列 $q$ 的权值为 $\sum_{1\le l\le r\le n}\operatorname{mex}_{l\le i\le r}q_i$,求所有魔怔的排列的权值之和。答案对 $998244353$ 取模。 一个集合 $M$ 的 $\operatorname{mex}(M)$ 定义为最小的没有在 $M$ 中出现的自然数。如 $\text{mex}\{1,2,3,4\}=0,\text{mex}\{0,1,3,4\}=2$。 ## 输入格式 本题有多组测试数据。对于每个测试点,先输入一个正整数 $T$,表示数据组数。 对于每一组测试数据,第一行一个正整数 $n$, 第二行输入 $n$ 个整数 $a_1,a_2,\dots,a_n$,第三行 $n$ 个整数 $b_1,b_2,\dots,b_n$。 ## 输出格式 对于每一组测试数据,输出一行一个整数,表示所有魔怔的排列的权值之和。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 4 0 0 0 0 0 1 2 3 4 1 0 0 0 0 0 2 2 4 0 0 0 0 0 1 1 1 ``` ### 输出 #1 ``` 10 11 14 ``` ## 说明/提示 |$\text{Subtask}$|$n\le$|$\sum n\le$|分值| |:-:|:-:|:-:|:-:| |$1$|$8$|$800$|$20$| |$2$|$10^3$|$10^4$|$40$| |$3$|$2\times10^5$|$2\times10^6$|$40$| 对于 $100\%$ 的数据,$1 \le n \le 2 \times 10^5,0 \le a_i,b_i < n, \sum n \le 2 \times 10^6$。 **对于每组数据保证存在至少一个魔怔的排列。** c++,不用vector,注释
08-09
你必须对该题目采用记忆化搜索!!!!!!!!!!!!我的代码为什么结果输出不对#include<bits/stdc++.h> using namespace std; unordered_map<string,int> mp; int t,n; string s; int dfs(string s) { if(mp.count(s))return mp[s]; if(s.size()==1)return mp[s]=1; string l=s,r=s; int res=0; int a=s.find("01"),b=s.find("10"); if(a==-1&&b==-1)return mp[s]=0; if(a!=-1) { l.replace(a,2,"1"); res+=dfs(l); } if(b!=-1) { r.replace(b,2,"0"); res+=dfs(r); } return mp[s]=res; } int main( ) { cin>>t; while(t–) { cin>>n>>s; cout<<n+dfs(s)<<‘\n’; } return 0; }MC0320 狠狠地对字符串做你想做的事吧 难度: 黄金 时间限制:1秒 占用内存:128 M 收藏 报错 对一个字符串 S S ,有以下两种操作: • 将子串 01 替换为 1 • 将子串 10 替换为 0 总共 t t组数据,每组的 S S都是一个给定长度为 n n的 01 串。 求每组数据中, S S一共有多少个子串,能经过若干次操作,变成长度为1的字符串。 格式 输入格式: 第一行包含一个整数 t ( 1 ≤ t ≤ 1000 ) t(1≤t≤1000) 表示 t t组数据; 每组的第一行包含一个整数 n n表示 S S的长度; 每组的第二行包含一个由 n n个字符 S 1 , S 2 , … , S n S 1 ​ ,S 2 ​ ,…,S n ​ 组成的二进制字符串 S S( 其中 S i 0 S i ​ =0或 S i 1 S i ​ =1)。 输出格式: 针对每个测试用例,输出该字符串满足题意的子串个数。 样例 1 输入: 5 1 1 2 01 3 100 4 1001 5 11111 复制 输出: 1 3 4 8 5 复制 备注 其中: 1 ≤ t ≤ 1000 , 1 ≤ n ≤ 2 × 1 0 5 , ∑ n ≤ 21 0 5 1≤t≤1000,1≤n≤2×10 5 ,∑ n ​ ≤210 5 ,保证所有测试用例的 n 总和不超过 2 × 1 0 5 2×10 5 。
最新发布
08-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值