BestCoder Round #84题解报告

本文针对BestCoder Round #84的比赛提供详细的解题思路与代码实现,包括Problem1001 Aaronson中关于寻找特定方程的最优解,Problem1002 Bellovin中关于最长上升子序列的构造问题,以及Problem1004 Dertouzos中关于最大正真因数的计数问题。

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

此文章可以使用目录功能哟↑(点击上方[+])

好久没办的bestcoder,今天重新开始做,结果着实被自己蠢哭,各种低端错,把自己坑掉分了...

链接→BestCoder Round #84

 Problem 1001 Aaronson

Accept: 0    Submit: 0
Time Limit: 4000/2000 MS (Java/Others)    Memory Limit : 131072/131072 K (Java/Others)

 Problem Description

Recently, Peter saw the equation . He wants to find a solution  in such a manner that is minimum and every x​i is non-negative.
给出一个不定方程 , 找出一组解 , 使得 最小, 并且每个x​i(0≤i≤m)都是非负的.

 Input

There are multiple test cases. The first line of input contains an integer T(1≤T≤10^5), indicating the number of test cases. For each test case:

The first contains two integers n and m(0≤n,m≤10^9).
输入包含多组数据, 第一行包含一个整数T(1≤T≤10^​5)表示测试数据组数. 对于每组数据:
第一行包含两个整数n和m(0≤n,m≤10^​9).

 Output

For each test case, output the minimum value of .

对于每组数据, 输出的最小值.

 Sample Input

10
1 2
3 2
5 2
10 2
10 3
10 4
13 5
20 4
11 11
12 3

 Sample Output

1
2
2
3
2
2
3
2
3
2

 Problem Idea

解题思路:

【题意】
我想中文题就不必解释了吧,唯一要注意的一点就是xi是非负整数


【类型】
暴力

【分析】
首先,不管三七二十一,先把2的各个次幂先打表保存

然后从满足条件的最大的次幂开始逐一判断,能取则取

这题被hack掉着实出乎意料,就因为手残,表没打全

【时间复杂度&&优化】
O(mT)

题目链接→HDU 5747 Aaronson

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 31;
const int M = 1005;
const int inf = 1000000007;
const int mod = 1000000007;
int s[N];
int main()
{
    int t,n,m,i,j,k,ans;
    s[0]=1;
    for(i=1;i<N;i++)
        s[i]=s[i-1]+s[i-1];
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%d%d",&n,&m);
        for(j=min(m,N-1);j>=0;j--)
            if(n>=s[j])
            {
                k=n/s[j];
                ans+=k;
                n-=k*s[j];
            }
        printf("%d\n",ans);
    }
    return 0;
}

 Problem 1002 Bellovin

Accept: 0    Submit: 0
Time Limit: 6000/3000 MS (Java/Others)    Memory Limit : 131072/131072 K (Java/Others)

 Problem Description

Peter has a sequence a1,a2,...,an and he define a function on the sequence -- F(a1,a2,...,an)=(f1,f2,...,fn), where fi is the length of the longest increasing subsequence ending with ai.

Peter would like to find another sequence b1,b2,...,bn in such a manner that F(a1,a2,...,an) equals to F(b1,b2,...,bn). Among all the possible sequences consisting of only positive integers, Peter wants the lexicographically smallest one.

The sequence a1,a2,...,an is lexicographically smaller than sequence b1,b2,...,bn, if there is such number i from 1 to n, that ak=bk for 1≤k<i and ai<bi.

Peter有一个序列a1,a2,...,an. 定义F(a1,a2,...,an)=(f1,f2,...,fn), 其中f​i是以ai结尾的最长上升子序列的长度.

Peter想要找到另一个序列b1,b2,...,bn使得F(a1,a2,...,an)和F(b1,b2,...,bn)相同. 对于所有可行的正整数序列, Peter想要那个字典序最小的序列.

序列a1,a2,...,an比b1,b2,...,bn字典序小, 当且仅当存在一个正整数i (1≤i≤n)满足对于所有的k (1≤k<i)都有ak = bk并且ai < bi.

 Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first contains an integer n (1≤n≤100000) -- the length of the sequence. The second line contains n integers a1,a2,...,an (1≤ai≤10^9).

输入包含多组数据, 第一行包含一个整数T表示测试数据组数. 对于每组数据:

第一行包含一个整数n (1≤n≤100000)表示序列的长度. 第二行包含n个整数a1,a2,...,an (1≤ai≤10^9).

 Output

For each test case, output n integers b1,b2,...,bn (1≤bi≤10^9) denoting the lexicographically smallest sequence.

对于每组数据, 输出n个整数b1,b2,...,bn (1≤bi≤10^9)表示那个字典序最小的序列.

 Sample Input

3
1
10
5
5 4 3 2 1
3
1 3 5

 Sample Output

1
1 1 1 1 1
1 2 3

 Problem Idea

解题思路:

【题意】
中文题面


【类型】
最长上升子序列

【分析】
一开始的时候还各种方法试来试去,结果自己的一组数据都过不了

后来才发现,原来这题就是求以ai结尾的最长上升子序列为多少

好吧,原来一直都是我想太多

于是乎,一个最长上升子序列模板搞定

【时间复杂度&&优化】
O(nlogn)

题目链接→HDU 5748 Bellovin

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 100005;
const int M = 1005;
const int inf = 1000000007;
const int mod = 1000000007;
int  a[N], f[N], d[N];    // f[i]用于记录 a[0...i]的最大长度
int bsearch(const int *f, int size, const int &a)
{
    int  l=0, r=size-1;
    while( l <= r )
    {
        int  mid = (l+r)>>1;
        if( a > d[mid-1] && a <= d[mid] )
            return mid;                // >&&<= 换为: >= && <
        else if( a <d[mid] )
                r = mid-1;
        else l = mid+1;
    }
}
int LIS(const int *a, const int &n)
{
    int  i, j, size = 1;
    d[0] = a[0]; f[0] = 1;
    for( i=1; i < n; ++i )
    {
        if( a[i] <= d[0] )             // <= 换为: <
            j = 0;
        else if( a[i] > d[size-1] ) // > 换为: >=
            j = size++;
        else
            j = bsearch(d, size, a[i]);

        d[j] = a[i]; f[i] = j+1;
    }
    return size;
}
int main()
{
    int  t,i,n;
    scanf("%d",&t);
    while(t--)
    {
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        scanf("%d",&n);
        for( i=0; i < n; ++i )
            scanf("%d", &a[i]);
        LIS(a, n);
        for(i=0;i<n;i++)
            printf("%d%c",f[i],i!=n-1?' ':'\n');
    }
    return 0;
}


 Problem 1004 Dertouzos

Accept: 0    Submit: 0
Time Limit: 7000/3500 MS (Java/Others)    Memory Limit : 131072/131072 K (Java/Others)

 Problem Description

A positive proper divisor is a positive divisor of a number n, excluding n itself. For example, 1, 2, and 3 are positive proper divisors of 6, but 6 itself is not.

Peter has two positive integers n and d. He would like to know the number of integers below n whose maximum positive proper divisor is d.

正整数x称为n的positive proper divisor, 当且仅当x∣n并且1≤x<n. 例如, 1, 2, 和3是6的positive proper divisor, 但是6不是.

Peter给你两个正整数n和d. 他想要知道有多少小于n的整数, 满足他们的最大positive proper divisor恰好是d.

 Input

There are multiple test cases. The first line of input contains an integer T(1≤T≤10^6), indicating the number of test cases. For each test case:

The first line contains two integers n and d(2≤n,d≤10^9).
输入包含多组数据, 第一行包含一个整数T(1≤T≤10^6)表示测试数据组数. 对于每组数据:
第一行包含两个整数n和d(2≤n,d≤10^9).

 Output

For each test case, output an integer denoting the answer.

对于每组数据, 输出一个整数.

 Sample Input

9
10 2
10 3
10 4
10 5
10 6
10 7
10 8
10 9
100 13

 Sample Output

1
2
1
0
0
0
0
0
4

 Problem Idea

解题思路:

【题意】
中文题面


【类型】
素数表+暴力

【分析】
首先,我们要清楚,怎样的整数,它的最大positive proper divisor恰好是d

即kd除本身以外最大因子是d,故k≠1,其次,我们需要发现,k只能是小于等于(d的最小质因子)的质数

不信?比如d=100,那我k只能取2,如果k=7,kd=700,那positive proper divisor应该为350,显然矛盾

故令y=xd, 如果d是y的maximum positive proper divisor, 显然要求x是y的最小质因子. 令mp(n)表示n的最小质因子, 那么就有x≤mp(d), 同时有y<n, 那么. 于是就是计算有多少个素数x满足.

当d比较大的时候,比较小, 暴力枚举x即可. 当d比较小的时候, 可以直接预处理出答案.


【时间复杂度&&优化】
O(Tlogn)

题目链接→HDU 5750 Dertouzos

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 100005;
const int M = 32000;
const int inf = 1000000007;
const int mod = 1000000007;
int prime[N],p,min_factor[N];
bool v[N];
void get_prime()
{
    memset(v,false,sizeof(v));
    for(int i=2;i<N;i++)
        if(!v[i])
        {
            prime[p++]=i;
            for(int j=i;j<N;j+=i)
            {
                if(!v[j])
                    min_factor[j]=i;
                v[j]=true;
            }
        }
}
int main()
{
    int t,n,d,k,ans,i;
    p=0;
    get_prime();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&d);
        k=(n-1)/d;
        if(d>=N)
        {
            for(i=0;prime[i]<k;i++)
                if(d%prime[i]==0)
                {
                    k=prime[i];
                    break;
                }
        }
        else
            k=min(k,min_factor[d]);
        ans=upper_bound(prime,prime+p,k)-prime;
        printf("%d\n",ans);
    }
    return 0;
}

菜鸟成长记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值