zoukankan      html  css  js  c++  java
  • CSP-S day1

    T1 临时换题(huan)
    1.1 题目描述
    现在都已经八点半了, pufanyi 现在因为 std 出锅很自闭,于是决定临时换题。原
    来的 Day1T1 将会被移到 Day2,现在你看到的是原来的 Day2T1。
    本题均使用十进制计数。
    和一般的女孩子一样,小小迪喜欢教钧钧数数。
    给定两个正整数 l 和 r,对于任意 x,满足 l ≤ x ≤ r,把 x 的所有约数全部写下
    来。对于每个写下来的数,只保留最高位的那个数码。求 [1, 9] 中每个数码出现的次数。
    这里的约数是指:对于正整数 y,如果正整数 x 使得存在正整数 k 有 kx = y, x 是
    y 的约数。
    1.2 输入输出格式
    1.2.1 输入格式
    从文件 huan.in 中读入数据。
    输入一行两个正整数 l 和 r。
    1.2.2 输出格式
    输出到文件 huan.out 中。
    输出一行 9 个非负整数,每两个数字之间用一个空格分开,第 i 个数表示数码 i 出
    现的次数。
    1.3 样例
    1.3.1 样例 1 输入
    1 4
    1.3.2 样例 1 输出
    4 2 1 1 0 0 0 0 0
    1.3.3 样例 1 解释
    数字 约数 最高位
    1 1 1
    2 1, 2 1, 2
    3 1, 3 1, 3
    4 1, 2, 4 1, 2, 4
    1.3.4 样例 2 输入
    233 238
    1.3.5 样例 2 输出
    13 10 4 2 2 1 3 0 1
    1.3.6 样例 2 解释
    数字 约数 最高位
    233 1, 233 1, 2
    234 1, 2, 3, 6, 9, 13, 18, 1, 2, 3, 6, 9, 1, 1, 2, 3, 7, 1, 2
    26, 39, 78, 117, 234
    235 1, 5, 47, 235 1, 5, 4, 2
    236 1, 2, 4, 59, 118, 236 1, 2, 4, 5, 1, 2
    237 1, 3, 79, 237 1, 3, 7, 2
    238 1, 2, 7, 14, 17, 1, 2, 7, 1, 1, 3, 1, 2
    34, 119, 238
    1.4 数据范围与提示
    本题共 10 个测试点,每个测试点 10 分。
    对于所有测试点,均有 l ≤ r。
    每个测试点的具体限制见下表。
    测试点编号 r 特殊性质
    1 ∼ 2 ≤ 10000 无
    3 ∼ 5 ≤ 107
    6 ∼ 7 ≤ 109 r − l ≤ 1000
    8 ∼ 10 无
    本题答案有 32 位整型溢出风险,故统计答案时请务必使用 64 位整型。


    思路:
    由题意可得 ans[getmax(i)]+=n/i
    暴力的话1e7可以过直接50分,1e9会TLE
    因为其实只需要考虑最高位对答案的贡献,并且我们发现在某一段区间内,对答案的贡献是一样的
    比如(50,100]=1
    而这个区间为 (n/k+1,n/k],贡献值为k;
    枚举首位遍历不同的区间
    1->(10,19)->(100-199)
    再在这个区间内根据 (n/k+1,n/k]划分区间
    最后答案累加a(当前区间的值得贡献)*d(区间长度)
    例:100
    30-39的区间
    a=3,区间33 (30,33)100/34=2,100/2=50,50和39进行比较(34,39)
    所以划分为(30,33)(34,39)

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 inline int read(){
     5     int s=0,w=1;
     6     char ch=getchar();
     7     while(ch<'0'||ch>'9'){if(ch=='-')w=-1,ch=getchar();}
     8     while(ch>='0'&&ch<='9'){s=s*10+ch-'0',ch=getchar();}
     9     return s*w;
    10 }
    11 ll ans[2][10],l,r;
    12 inline void solve(int tot,int n){
    13     for(int i=1;i<=9;i++){
    14         for(int j=1;j*i<=n;j*=10){
    15             ll d,l=1ll*i*j,r=min(1ll*i*j+j-1,(ll)n);//d区间长度,l,r左右边界
    16             for(ll k=l;k<=r;k+=d){
    17                 ll a=n/k,b=n%k;//a为区间的统一贡献值,b=n-a*k;
    18                 d=1+min(b/a,r-k);//b/a=n/a-k,(n/a)即为断点的值,r-k防止越界
    19                 ans[tot][i]+=a*d; 
    20             } 
    21         }
    22     }
    23 }
    24 int main(){
    25     freopen("huan.in", "r", stdin);
    26     freopen("huan.out", "w", stdout);
    27     scanf("%d%d", &l, &r);
    28     solve(0, r), solve(1, l - 1);
    29     for (int i = 1; i <= 9; ++i) {
    30         printf("%lld ", ans[0][i] - ans[1][i]);
    31     }
    32     return 0;
    33 }
  • 相关阅读:
    现代软件工程 第一章 概论 第4题——邓琨
    现代软件工程 第一章 概论 第9题——邓琨
    现代软件工程 第一章 概论 第7题——张星星
    现代软件工程 第一章 概论 第5题——韩婧
    hdu 5821 Ball 贪心(多校)
    hdu 1074 Doing Homework 状压dp
    hdu 1074 Doing Homework 状压dp
    hdu 1069 Monkey and Banana LIS变形
    最长上升子序列的初步学习
    hdu 1024 Max Sum Plus Plus(m段最大子列和)
  • 原文地址:https://www.cnblogs.com/Shayndel/p/11822280.html
Copyright © 2011-2022 走看看