首页 > 试题广场 >

函数求值

[编程题]函数求值
  • 热度指数:2069 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给定正整数N,函数F(N)表示小于等于N的自然数中1和2的个数之和,例如:1,2,3,4,5,6,7,8,9,10序列中1和2的个数之和为3,因此 F(10)=3。输入N,求F(N)的值,1=<N<=10^100(10的100次方)若F(N)很大,则求F(N)mod20123的值


输入描述:


输出描述:
示例1

输入

10
10

输出

3
3
这数位DP能被这么多暴力过我是没想到的 只能说评测鸡太牛了
发表于 2022-04-22 19:54:50 回复(1)
测试用例有些问题
定义G(999...9) = G(k), 其中 k 为 9 的个数
G(k) = 2 * 10^(k - 1) + 10 * G(k - 1)
G(1) = 2
e.g. F(9) = G(1) = 2
F(99) = G(2) = 2 * 10^1 + 10 * G(1) = 2 * 10 + 10 * 2 = 40
...
F(1234) = (统计 0000 到 0999 个数) + (统计 1000 到 1234 个数)
             = F(999) + {[1 * (234 + 1)] + F(234)}
F(2234) = (统计 0000 到 0999 个数) + (统计 1000 到 1999 个数) + (统计 2000 到 2234 个数)
            = F(999) + {[1 * (999 + 1)] + F(999)} + {[1 * (234 + 1)] + F(234)}

   (其他平台 N诺 (http://noobdream.com/DreamJudge/Issue/page/1421/#) ac 了)
#include <iostream>
#include <string>

using namespace std;

const int MOD = 20123;

void removeprezeros(string& s) {
	while (!s.empty() && s[0] == '0') {
		s.erase(s.begin());
	}
	if (s.empty()) {
		s = "0";
	}
}

int smod(string& s) {
	int rest = 0;
	for (int i = 0; i < s.length(); i++) {
		int v = rest * 10 + (s[i] - '0');
		rest = v % MOD;
	}
	return rest;
}

void sincr(const string& s, string& ans) {
	int carry = 1;
	string temp = "";
	for (int i = s.length() - 1; i >= 0; i--) {
		int v = s[i] - '0' + carry;
		temp.insert(temp.begin(), (char)((v % 10) + '0'));
		carry = v / 10;
	}
	if (carry > 0) {
		temp.insert(temp.begin(), (char)(carry + '0'));
	}
	ans.clear();
	ans = move(temp);
}

int funkmod(int k, int* tenmods) {
	if (k == 1) {
		return 2 % MOD;
	} else if (k <= 0) {
		return 0 % MOD;
	} else {
		return (
			(((2 % MOD) * tenmods[k - 1]) % MOD) +
			(((10 % MOD) * (funkmod(k - 1, tenmods))) % MOD)
		) % MOD;
	}
}

int fun(const string& s, int* funks, int* tens) {
	if (s.length() <= 0) {
		return 0;
	} else if (s.length() == 1) {
		int v = s[0] - '0';
		return v == 0 ? 0 : v == 1 ? 1 : 2;
	} else {
		int k = s.length();
		int ans = 0;
		int fv = s[0] - '0';
		for (int i = 0; i < fv; i++) {
			ans += funks[k - 1];
			ans %= MOD;
			if (i == 1 || i == 2) {
				ans += tens[k - 1];
				ans %= MOD;
			}
		}
		string temp = s.substr(1, k - 1);
		if (fv == 1 || fv == 2) {
			string incred;
			sincr(temp, incred);
			ans += smod(incred);
			ans %= MOD;
		}
		ans += fun(temp, funks, tens);
		ans %= MOD;
		return ans;
	}
}


int main() {
	int tenmods[103] = {0};
	int t = 1;
	for (int i = 0; i <= 102; i++) {
		tenmods[i] = t;
		tenmods[i] %= MOD;
		t *= 10;
		t %= MOD;
	}
	int funks[103] = {0};
	for (int i = 1; i <= 102; i++) {
		funks[i] = funkmod(i, tenmods);
	}
	char cline[500] = {0};
	while (scanf("%s", &cline) == 1) {
		string line = cline;
		removeprezeros(line);
		printf("%d\n", fun(line, funks, tenmods));
	}
}




发表于 2021-01-08 16:21:27 回复(1)
这个题数据有问题,在N诺上正确通过了😂😂😂

编辑于 2020-04-28 11:03:09 回复(0)
/**
比如输入12345,那么先算F(1),再由F(1)算出F(12),依次再算出F(123),F(1234),F(12345);
主要计算的就是res=(res-cnt)*10+cnt*(t+1)+num*2+min(t,2);
res代表循环到此位的结果;num是实际输入的数;cnt是num这个数中1,2的数量;

例如F(12)=res,需要算F(123)

1.显然12变成了12X的形式,所以原来1-11中每一个数都可以加上一个个位(因为不知道个位是不是9,所以最后一个12不能乘10,以后单独计算),
而个位是从0-9,所以原来的每个数都有10中变化,而最后一个数12的1,2的数量为cnt,所以有(res-cnt)*10,;

2.上一步中余有一个12没有计算,显然12X这个数的个位只能是0-3,所以有cnt*(t+1);

3.上面的计算中都没有考虑对个位为1,2的计数,个位为1,2的显然是每10个数中有2个,所以有num*2(例如12中0-11都可以个位是1,2)
4.12X个位的1,2个数,直接判断就行,min(t,2);
*/
import java.util.*;
public class Main{
    private static int Mod = 20123;
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            char[] chs = in.nextLine().toCharArray();
            int len = chs.length;
            int res = 0;
            int num = 0;
            int cnt = 0;
            for(int i = 0; i < len; i++){
                int curNum = chs[i] - '0';
                res = (res - cnt) * 10 + cnt * (curNum + 1) + num * 2 + Math.min(curNum, 2);
                if(curNum == 1 || curNum == 2)
                    cnt++;
                num = (num * 10 + curNum) % Mod;
                res = res % Mod;
            }
            System.out.println(res);
        }
    }
}

发表于 2021-06-13 22:06:26 回复(0)
//程序提交后,系统测试过程中提供的数据可能存在问题!
//验错举例:输入99与98,输出应该相同,但是系统测试数据中,结果分别为42与40;
//下面代码参考网络开源代码:
#include <stdio.h>
#include <string.h>
 
int mod(int x)
{
     return x%20123;
}
 
int Sumls(char str[],int length,int version)
{
    int curPos=length-1,iFactor=1;
    int iCount=0;
    while(curPos>=0)
    {
        int iLowerNum=0,iCurNum=0,iHigherNum=0;
        for(int i=curPos+1;i<length;i++){
            iLowerNum=mod(mod(iLowerNum*10)+str[i]-'0');
        }
        iCurNum=str[curPos]-'0';
        for(int i=0;i<curPos;i++){
            iHigherNum=mod(mod(iHigherNum*10)+str[i]-'0');
        }
        if(iCurNum<version){
            iCount=mod(iCount+mod(iHigherNum*iFactor));
        }
        else if(iCurNum==version){
            iCount=mod(iCount+mod(iHigherNum*iFactor+iLowerNum+1));
        }
        else{
            iHigherNum++;
            iCount=mod(iCount+mod(iHigherNum*iFactor));
        }
        curPos--;
        iFactor=mod(iFactor*10);
    }
    return iCount; 
}
 
int main()
{
    char str[500];
    memset(str,0,sizeof(str));
    while(scanf("%s",&str)!=EOF)
    {
        int length=strlen(str);
        int res1=Sumls(str,length,1);
        int res2=Sumls(str,length,2);
        int res=res1+res2;
        printf("%d\n",mod(res));
        memset(str,0,sizeof(str));
    }
    return 0;
}

发表于 2021-03-09 08:31:54 回复(0)
#include<iostream>
#include<string>
using namespace std;

string s;

int Pow(int n)
{
    int d = 10,res = 1;
    while(n)
    {
        if(n & 1)
        {
            res = (d * res) % 20123;
        }
        d = (d * d) % 20123;
        n >>= 1;
    }
    return res;
}

int GetNum(int i,int j)
{
    int d = 0;
    for(i;i <= j;i++)
    {
        d = 10 * d + s[i] - '0';
        d %= 20123;
    }
    return d;
}

int main()
{
    while(cin >> s)
    {
        int sum = 0;
        for(int i = 0;i < s.size();i++)
        {
            int a = GetNum(0,i - 1);
            int b = GetNum(i + 1,s.size() - 1);
            int p = Pow(s.size() - i - 1);
            if(s[i] > '2')
            {
                sum += ((a + 1) * 2 * p) % 20123;
            }
            else if(s[i] == '2')
            {
                sum += ((a * 2 + 1) * p + b + 1) % 20123;
            }
            else if(s[i] == '1')
            {
                sum += (((a * 2) * p + b + 1)) % 20123;
            }
            else if(s[i] == '0')
            {
                sum += ((a * 2) * p) % 20123;
            }
            sum %= 20123;
        }
        cout << sum << endl;
    }
    return 0;
}

发表于 2021-02-24 21:17:46 回复(0)
快去请华科平凡!
发表于 2021-02-20 10:16:50 回复(0)
 动态规划,但这乱七八糟的测试用例你跟我闹呢?
#include <bits/stdc++.h>
using namespace std;
int main()
{
    string input;
    while(cin>>input)
    {
        int n=input.length();
        string s=input;
        reverse(input.begin(),input.end());
        int x=0,p=1,k=20123,res=0,m=0;
        for(int i=0;i<n;++i)
        {
            int last=input[i]-'0';
            int smallpart=(last*x%k+(last>1?p:0)+(last>2?p:0))%k;
            int equalpart=((last==1||last==2?(m+1)%k:0)+res)%k;
            res=(smallpart+equalpart)%k;
            x=(2*p%k+10*x%k)%k;
            m=((last*p)%k+m)%k;
            p=p*10%k;
        }
        cout<<res<<endl;
    }
    return 0;
}



发表于 2020-04-18 20:12:49 回复(0)
因为涉及到大数问题,用C比较麻烦,所以改用python。但是在9999999...999那里不能通过,大家帮看看问题出在哪里?
在函数counti中依次统计i出现在个位、十位、百位...的次数。
经过验证,1到1000的结果正确。
def counti(N, i):
    count=0; base=10; tmp=N
    while(tmp):
        count += N//base*base//10
        if(N%base >= (i*base//10)):
            if(N%base < ((i+1)*base//10)):
                count += (N%(base//10) + 1);
            else:
                count += base//10
        base *= 10
        tmp //= 10
    return count
while True:
    try:
        N = int(input())
        result = (counti(N,1)+counti(N,2))%20123
        print(result)
    except:
        break
编辑于 2020-01-02 11:39:30 回复(0)
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner cs = new Scanner(System.in);
        while(cs.hasNext()){
            long n = cs.nextLong();
            if(n<1 || n>100000000){
                n = 20123;
            }
            int x;
            String str;
            int i ;
            int k;
            int count = 0;
            for(i=1 ; i<n+1 ; i++){
                str = "" + i ;
                k = str.length();
                for(int j =0;j<k;j++){
                    if(str.charAt(j) == '1' || str.charAt(j) == '2')
                        count = count + 1;
                    
                }
            }
            System.out.println(count);
        }
    }
}

发表于 2019-06-28 20:55:00 回复(0)
此段代码在我本地C编译器中已经试验了,我输入 11 ,对应就是输出5,但是此处的结果显示说我输出的是3,真心没有明白,严重怀疑此验证的结果有误!
#include <stdio.h>
#include <math.h>

#define LEN 1000

int main(void)
{
    unsigned int count_a = 0,count_b = 0;
    unsigned int n,i,j,k,temp;
    char str[LEN] = {0};
    unsigned int ret = 0,sum = 0;
    
    scanf("%d",&n);
    for(i=n;i>=1;i--)
    {
        temp = n;
        sprintf(str,"%d",i);
        
        while(temp)
        {
            sum++;
            temp /=10;
        }
        for(j=0;j<sum;j++)
        {
            if(str[j] == '1')
                count_a++;
            else if(str[j] == '2')
                count_b++;
            else
                continue;
        }
    }
    ret = count_a + count_b;
    printf("%d\n",ret);
    printf("%d\n",(ret%20123));
    
    return 0;
}
发表于 2019-05-29 01:14:55 回复(1)
import sys

def solu(m):
    m=int(m)
    k=list(str(m))
    count=0
    l=len(k)
    if int(k[0])>2:
        count+=2*10**(l-1)
    else:
        count+=(m+1-10**(l-1))
    count=count
    for i in range(1,l):
        if int(k[i])>2:
            count+=((int(str(m)[0:i]))+1)*2*10**(l-i-1)
        elif int(k[i])==0:
            count+=(int(str(m)[0:i]))*2*10**(l-i-1)
        else:
            count+=((int(str(m)[0:i]))+1)*2*10**(l-i-1)-(3*10**(l-i-1)-int(str(m)[i:])-1)
    return count%(20123)
for line in sys.stdin:
    print(int(solu(line)))
发表于 2019-05-16 17:38:20 回复(1)
我怎么感觉这个题有点问题呢,没读懂
发表于 2019-04-29 19:48:24 回复(1)
import sys
def fun1(num):
    sum1 = 0
    for i in range(num+1):
        t = str(i)
        for x in t:
            if x == '1' or x == '2':
                sum1 += 1
    return sum1

# list1 = []
# str1 = sys.stdin.readlines()
# for y in str1:
#     print(fun1(int(y)))
num = int(input())
print(fun1(num))
发表于 2019-04-04 23:20:54 回复(0)
这个题检测有问题
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        ArrayList<String> str =new ArrayList<>();
        //in.nextLine();

            str.add(in.nextLine());
        

       for (int j=0;j<str.size();j++)
       {
           BigInteger count = new BigInteger(str.get(j));
           String s = "";
           BigInteger shuzi = new BigInteger("1");
           BigInteger shu = new BigInteger("0");
           BigInteger temp = count.subtract(new BigInteger("0"));
           while (!temp.equals(shu)){
               s = s+temp.toString();
               temp = temp.subtract(shuzi);

           }
           int Sum = 0;
           for (int i =0;i<s.length();i++)
           {
               char t = s.charAt(i);
               if (t=='1'||t=='2')
               {
                   Sum++;
               }
           }
           System.out.print("\n"+Sum);
       }
    }





}


发表于 2019-03-06 19:19:32 回复(2)
#include<stdio.h>
#include<string.h>

char str[102];

int Pow10(int n){
    int ret = 1;
    int i = n;
    while(i--){
        ret *= 10;
        ret %= 20123;
    }
    return ret;
}

int Get(int a, int b){
    int i = b;
    int ret = 0;
    while(i != a-1){
        ret += (str[i]-'0')*Pow10(b-i);
        ret %= 20123;
        i--;
    }
    return ret;
}

int main(){
    while(scanf("%s", str) == 1){
        int len = strlen(str);
        int i;
        int sum = 0;
        for(i = 0; i < len; i++){
            int n = len-i-1;
            if(str[i] > '2'){
                sum += 2*Pow10(n) *(Get(0, i-1) + 1);
            }else if(str[i] == '2'){
                sum += 2*Pow10(n) * Get(0, i-1) + Pow10(n) + Get(i+1, len-1) + 1;
            }else if(str[i] == '1'){
                sum += 2*Pow10(n) * Get(0, i-1) + Get(i+1, len-1) + 1;
            }else{
                sum += 2*Pow10(n) * Get(0, i-1);
            }
            sum %= 20123;
        }
        printf("%d\n", sum); /***********check**********/
    /*     int num;     sum = 0;     sscanf(str, "%d", &num);     for(i = 1; i <= num; i++){         char temp[11];         sprintf(temp, "%d", i);         int j;         for(j = 0; j < strlen(temp); j++){             if(temp[j] == '1' || temp[j] == '2')                 sum++;             if(sum == 20123)                 sum = 0;         }     }     printf("%d\n", sum); */
    }
    return 0;
}
这题和暴力解法能对上,但是和答案对不上啊,觉得答案可能有点问题。
发表于 2019-02-22 13:32:39 回复(0)
我就想知道为什么是42 怎么数出来的
发表于 2019-02-22 01:47:11 回复(1)

问题信息

上传者:小小
难度:
17条回答 3658浏览

热门推荐

通过挑战的用户

查看代码