BestCoder Round #84 <LIS 2进制 思维>

本文解析了三项算法挑战赛题目,包括寻找方程最优解、构造序列及求解特定整数计数问题。通过详细的思路说明与示例代码,帮助读者理解算法设计与实现。

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

Aaronson

 
 Accepts: 607
 
 Submissions: 1869
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
Problem Description

Recently, Peter saw the equation x_{0}+2x_{1}+4x_{2}+...+2^{m}x_{m}=nx0+2x1+4x2+...+2mxm=n. He wants to find a solution (x_0,x_1,x_2,...,x_m)(x0,x1,x2,...,xm) in such a manner that \displaystyle\sum_{i=0}^{m} x_ii=0mxi is minimum and every x_ixi (0 \le i \le m0im) is non-negative.

Input

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

The first contains two integers nn and mm (0 \le n,m \le 10^9)(0n,m109).

Output

For each test case, output the minimum value of \displaystyle\sum_{i=0}^{m} x_ii=0mxi.

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


Aaronson

 
 Accepts: 607
 
 Submissions: 1869
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
给出一个不定方程x_{0}+2x_{1}+4x_{2}+...+2^{m}x_{m}=nx0+2x1+4x2+...+2mxm=n, 找出一组解(x_0,x_1,x_2,...,x_m)(x0,x1,x2,...,xm), 使得\displaystyle\sum_{i=0}^{m} x_ii=0mxi最小, 并且每个x_ixi (0 \le i \le m0im)都是非负的.
输入描述
输入包含多组数据, 第一行包含一个整数TT (1 \le T \le 10^5)(1T105)表示测试数据组数. 对于每组数据:

第一行包含两个整数nnmm (0 \le n,m \le 10^9)(0n,m109).
输出描述
对于每组数据, 输出\displaystyle\sum_{i=0}^{m} x_ii=0mxi的最小值.
输入样例
10
1 2
3 2
5 2
10 2
10 3
10 4
13 5
20 4
11 11
12 3
输出样例
1
2
2
3
2
2
3
2
3
2


思路:

尽量取大的---


代码:

#include<cstdio>
int shu[33];
void ppp()
{
    shu[0]=1;
    for (int i=1;i<32;i++)
    shu[i]=shu[i-1]*2;
}
int main()
{
    ppp();
    int t;scanf("%d",&t);
    while (t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        if (m>31) m=31;
        int s=0;
        for (int i=m;i>=0;i--)
        {
            if (n>=shu[i])
            {
                s+=n/shu[i];
                n-=n/shu[i]*shu[i];
            }
        }
        printf("%d\n",s);
    }
    return 0;
}



Bellovin

 
 Accepts: 428
 
 Submissions: 1685
 Time Limit: 6000/3000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
Problem Description

Peter has a sequence a_1,a_2,...,a_na1,a2,...,an and he define a function on the sequence -- F(a_1,a_2,...,a_n)=(f_1,f_2,...,f_n)F(a1,a2,...,an)=(f1,f2,...,fn), where f_ifi is the length of the longest increasing subsequence ending with a_iai.

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

The sequence a_1, a_2, ..., a_na1,a2,...,an is lexicographically smaller than sequence b_1, b_2, ..., b_nb1,b2,...,bn, if there is such number ii from 11 to nn, that a_k = b_kak=bk for 1 \le k < i1k<i and a_i < b_iai<bi.

Input

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

The first contains an integer nn (1 \le n \le 100000)(1n100000) -- the length of the sequence. The second line contains nn integers a_1,a_2,...,a_na1,a2,...,an (1 \le a_i \le 10^9)(1ai109).

Output

For each test case, output nn integers b_1,b_2,...,b_nb1,b2,...,bn (1 \le b_i \le 10^9)(1bi109) denoting the lexicographically smallest sequence.

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

Bellovin

 
 Accepts: 428
 
 Submissions: 1685
 Time Limit: 6000/3000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
Peter有一个序列a_1,a_2,...,a_na1,a2,...,an. 定义F(a_1,a_2,...,a_n)=(f_1,f_2,...,f_n)F(a1,a2,...,an)=(f1,f2,...,fn), 其中f_ifi是以a_iai结尾的最长上升子序列的长度.

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

序列a_1, a_2, ..., a_na1,a2,...,anb_1, b_2, ..., b_nb1,b2,...,bn字典序小, 当且仅当存在一个正整数ii (1 \le i \le n)(1in)满足对于所有的kk (1 \le k < i)(1k<i)都有a_k = b_kak=bk并且a_i < b_iai<bi.
输入描述
输入包含多组数据, 第一行包含一个整数TT表示测试数据组数. 对于每组数据:

第一行包含一个整数nn (1 \le n \le 100000)(1n100000)表示序列的长度. 第二行包含nn个整数a_1,a_2,...,a_na1,a2,...,an (1 \le a_i \le 10^9)(1ai109).
输出描述
对于每组数据, 输出nn个整数b_1,b_2,...,b_nb1,b2,...,bn (1 \le b_i \le 10^9)(1bi109)表示那个字典序最小的序列.
输入样例
3
1
10
5
5 4 3 2 1
3
1 3 5
输出样例
1
1 1 1 1 1
1 2 3


运用LIS---求法,求出以每一位结尾的最长链长度---

每个的长度的排序是最优小字典序--



代码:

#include<cstdio>
#include<cstring>
#define MA 100100
int t,n,ge;
int kp[MA];
int shu[MA];
int chu[MA];
int zhao(int xx)
{
    int l=0,r=ge-1,mid,ans=0;
    while (r>=l)
    {
        mid=(l+r)/2;
        if (kp[mid]>=xx)
        {
            ans=mid;
            r=mid-1;
        }
        else
        l=mid+1;
    }
    return ans;
}
int main()
{
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);ge=0;
        for (int i=0;i<n;i++)
        {
            scanf("%d",&shu[i]);
            if (ge==0)
            {
                chu[i]=1;
                kp[ge++]=shu[i];
            }
            else
            {
                if (shu[i]>kp[ge-1])
                {
                    chu[i]=ge+1;
                    kp[ge]=shu[i];
                    ge++;
                }
                else
                {
                    chu[i]=zhao(shu[i]);
                  //  if (chu[i]!=-1)
                   // {
                        kp[chu[i]]=shu[i];
                        chu[i]++;
                   /* }
                    else
                    {
                        chu[i]=1;
                    }*/
                }
            }
        }
        for (int i=0;i<n-1;i++)
        printf("%d ",chu[i]);
        printf("%d\n",chu[n-1]);
    }
    return 0;
}


Dertouzos

 
 Accepts: 76
 
 Submissions: 1357
 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 nn, excluding nn itself. For example, 1, 2, and 3 are positive proper divisors of 6, but 6 itself is not.

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

Input

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

The first line contains two integers nn and dd (2 \le n, d \le 10^9)(2n,d109).

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

Dertouzos

 
 Accepts: 76
 
 Submissions: 1357
 Time Limit: 7000/3500 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
正整数xx称为nn的positive proper divisor, 当且仅当x | nxn并且1 \le x < n1x<n. 例如, 1, 2, 和3是6的positive proper divisor, 但是6不是.

Peter给你两个正整数nndd. 他想要知道有多少小于nn的整数, 满足他们的最大positive proper divisor恰好是dd.
输入描述
输入包含多组数据, 第一行包含一个整数TT (1 \le T \le 10^6)(1T106)表示测试数据组数. 对于每组数据:

第一行包含两个整数nndd (2 \le n, d \le 10^9)(2n,d109).
输出描述
对于每组数据, 输出一个整数.
输入样例
9
10 2
10 3
10 4
10 5
10 6
10 7
10 8
10 9
100 13
输出样例
1
2
1
0
0
0
0
0
4


BC官方解析:

随便推导下, 令y=xdy=xd, 如果ddyy的maximum positive proper divisor, 显然要求xxyy的最小质因子. 令mp(n)mp(n)表示nn的最小质因子, 那么就有x \le mp(d)xmp(d), 同时有y < ny<n, 那么x \le \lfloor \frac{n-1}{d} \rfloorxdn1. 于是就是计算有多少个素数xx满足x \le \min{mp(d), \lfloor \frac{n-1}{d} \rfloor}xmin{mp(d),dn1}.

dd比较大的时候, \lfloor \frac{n-1}{d} \rfloordn1比较小, 暴力枚举xx即可. 当dd比较小的时候, 可以直接预处理出答案. 阈值设置到10^6 \sim 10^7106107都可以过.


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
int kp,shu[350000],ge[350000];
void da()
{
    kp=0;
    memset(shu,0,sizeof(shu));
    memset(ge,0,sizeof(ge));
    int i,j;
    for (i=2;i<32000;i++)
    {
        if (shu[i]==0)
        {
            ge[kp++]=i;
            for (j=i*i;j<32000;j+=i)
                shu[j]=1;
        }
    }
}
int main()
{
    da();
    int t,n,d;scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d",&n,&d);
        n=(n-1)/d;
        n=min(n,d);
        for (int i=0;i<kp;i++)
        {
            if (d%ge[i]==0||ge[i]>n)//质数最多查一个d的因数---且最大到n--
            {
                if (ge[i]>n)
                printf("%d\n",i);
                else
                printf("%d\n",++i);
                break;
            }
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值