Gym - 101778B Ran and the Lock Code(讨论+二分,好题)

B. Ran and the Lock Code
time limit per test
3.0 s
memory limit per test
256 MB
input
standard input
output
standard output

Two days ago, a woman called Fumiyo Edogawa knocked the door of Kogoro Mouri home and claimed that she is Conan's mom. Fumiyo introduced herself as Conan's mother and used fake documents to prove this. Conan, Kogoro Mouri, and his daughter Ran believed her. So, Conan went with her.

Ran was worried about Conan. After investigations, Ran discovered that Conan has been kidnapped! Ran called the police and they helped her to find Conan's location. When they arrived at that location, Ran shocked because she discovered that Conan is detained inside a locked coffin.

After examining the coffin, Ran discovered that it is locked using a modern electronic lock. Ran can open the lock only by solving Tmysteries. In each mystery, Ran is giving two numbers n and a, and she needs to find the maximum number of distinct elements that can exist in a list of n positive elements with an average equals to a.

Ran knows that time is running out of her, and she must expedite in solving the mysteries to get Conan out of the coffin before his breath stopped. Ran asked you to help her in solving the mysteries. Will you leave Conan to die smothered or will you help Ran solving the mysteries?

Input

The first line contains an integer T (1 ≤ T ≤ 105), in which T is the number of mysteries.

Then T lines follow, giving the mysteries. Each line contains two integers n and a (1 ≤ n, a ≤ 109), in which n is the number of elements in the list, and a is the required average of that list.

Output

For each test case, print a single line containing the maximum number of distinct elements that can exist in a list of n positive elements with an average equals to a.

Example
input
Copy
3
2 4
5 1
8 4
output
Copy
2
1
7
Note

The average of a list of n elements x1x2...xn is defined as the ratio between the sum of the n elements and n. More formally:

In the first test case, Ran is asked to find the maximum number of distinct elements that can exist in a list of 2 positive elements with an average equals to 4. Ran can choose a list such as [3, 5]. So, the number of distinct elements is 2.


题意:要你构造一个包含n个元素(正整数)的序列,其均值为a,求这个序列中最多包含多少个不同的数

我的做法是讨论+二分过了,或许有更好的解法。(下面m代替n)

当m<=(a-1)*2时  显然答案即为m,即 a-1,a+1这样构造,m为奇数时补上a。

当m>(a-1)*2时,显然1,2,..,a-1,a,a+1,...,2*a-1符合条件。这是2*a-1个数。

然后对于剩下的可构造的tmp=m-(2*a-1)个数,我二分可以再添k个不同的数,即2*a,...,2*a+k-1

然后要使添加的数均值为a,就需要补一些数使sum(补的数+2*a+...+2*a+k-1)%m==0且(补的数的数量+k)<=tmp。

然后需要注意的是凑sum的时候直接凑到sum-sum(2*a+...+2*a+k-1)>=cnt的最小补得数的数量,否则会TLE。。。

还有就是a=1的情况要特判。。。

不懂的话看代码吧:(n为n,m为a)

#pragma comment(linker,"/STACK:102400000,102400000")
#include<bits/stdc++.h>
#define maxn 1000010
#define ll long long
#define inf 1e9+7
using namespace std;
const long long mod=1e9+7;
ll n,m,q,k,flag,x,f,y,p;
ll ans,tmp,cnt;
ll mysum(ll x,ll y)
{
    return ((y+1)*y)/2-((x-1)*x)/2;
}
bool jud(ll k)
{
    ll tmp=mysum(2*m,2*m+k-1);
    ll cm=tmp+(m-(tmp%m));
    ll cnt=cm/m-k;
    ll sum;
    if(cnt+k>n) return 0;
    while(cm-tmp<cnt)
    {
        sum=cnt-(cm-tmp)-1;
        sum=(sum/m+1);
        cm+=sum*m;
        cnt+=sum;
        if(cnt+k>n) return 0;
    }
    return 1;
}
int main()
{
    int T,cas;
    scanf("%d",&T);
    {
        while(T--){
        scanf("%lld %lld",&n,&m);
        if(m==1) ans=1;
        else if(((m-1)*2)<=n)
        {
            ans=(m-1)*2;
            n-=ans;
            if(n) {n--;ans++;}
            ll l=0,r=n;
            ll tmp=0;
            while(l<=r)
            {
                ll mid=(l+r)/2;
                if(jud(mid))
                {
                    tmp=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            ans+=tmp;
        }
        else
        {
             ans=n;
        }
        printf("%lld\n",ans);
        }
    }
    return 0;
}

有幸要到了一份大佬的代码,直接二分能构造多少个不同的数,代码很短,非常神奇,也贴在这里:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f;
#define mod 1000000007
long long n,T,ans,m,x;
long long erfen(long long p,long long all)
{
    long long mid=-1,l=1,r=n;
    while(1)
    {
        if(mid==(l+r)/2) break;
        mid=(l+r)/2;
        if((1+mid)*mid/2+(n-mid)>all) r=mid;
        else l=mid;
    }
    return l;
}
int main()
{
   scanf("%lld",&T);
   while(T--)
   {
       scanf("%lld%lld",&n,&m);
       if(m==1) printf("1\n");
       else if(((1+n)*n/2)<=(n*m))
       {
           printf("%lld\n",n);
       }
       else
       {
           x=erfen(n,n*m);
           printf("%lld\n",x);
       }

   }
}

其实说它是好题主要还是因为我现在的水平正好缺这样难度的题目来提升思维等级。。。

不过对于非常菜的我来说还是想了好几个小时。。。

猜你喜欢

转载自blog.csdn.net/lsd20164388/article/details/80312263