首页 > 代码库 > [BestCoder] Round #6

[BestCoder] Round #6

1001

http://acm.hdu.edu.cn/showproblem.php?pid=4981

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1002;
int num[maxn];
int n;

int main()
{
    while(rd(n)!=EOF)
    {
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            rd(num[i]);
            sum+=num[i];
        }
        sort(num+1,num+1+n);
        if(1.0*sum/n>=num[(1+n)/2])
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}

1002

http://acm.hdu.edu.cn/showproblem.php?pid=4982

题意为:
给出n,k,问能不能把n拆成k个不同的正整数相加,且其中k-1个数的和为完全平方数。
比如 n=22 ,k =4, 22可以拆成 1+5+6+10,且 1+5+10=4*4
BESTCODER主页上的题解:
PS:这道题目原来是要求输出一种可行方案的,所以下面题解是按照输出方案的思想搞的。
分析:
我们尝试枚举那个完全平方数 S,然后看能否将他拆分为 K-1 个数,并且不用到N-S
这一步可以用贪心+一次调整来搞定。为了保证 K-1 个数都不同,我们尝试尽量用 1,2,3...这些连续自然数来构造,如果 N-S 出现在这些数中,那么将 N-S 移除,再新加一个数。如果这样都不能拆分成 K-1 个数,那么这个 S 肯定不行。
现在考虑已经用上述方法拆分了,我们需要判断这个拆分是否可行。会产生问题的只有最后一个数,这个数可能和 N-S 一样,也可能出现在之前的序列。如果是出现在之前的序列,那么这个拆分也是不靠谱的。如果和 N-S 一样,那么分两种情况
1. N-S 曾出现在之前的序列,那么显然这个拆分也是不靠谱的
2. N-S 比倒数第二个数大,对于这种我们可以通过调整最后一个数和倒数第二个数的大小,来使得这个拆分成立,假设最后一个数为 a,倒数第二个为 b,只要 a-1,b+1 就好了。当然如果 a-1 = b+1 这个拆分也是不靠谱的这道题目就这样搞定了,其实没必要找所有的完全平方数,只要找小于 N 与 N 最接近的完全平方数就好了。
枚举出一个完全平方数,那么剩下的数就确定了,下面就开始判断剩下的那个数是否符合题意。
构造出完全平方数的k-1个数,从小到大,贪心,1,2,3.....

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int n,k;

bool ok(int s)
{
    int last=n-s;//最后一个数,k-1个数以外的那个数
    int k1=s,k2=1;//k1为k-1个数里面最后一个数,k2为倒数第二个数
    ///构造k-2个数
    for(int i=1;i<=k-2;i++)
    {
        if(k2==last)//与最后一个数相等,不可以
            k2++;
        k1-=k2;//这里写成k1=s-k2了
        if(k1<=k2)
            return false;
        k2++;
    }
    k2--;
    while(1)//调整k-1个数中的最后两个
    {
        if(k1<=k2)
            return false;
        if(k1!=last)
            return true;
        k1--;//
        k2++;
    }
}

int main()
{
    while(rd2(n,k)!=EOF)
    {
        int m=sqrt(n);
        if(m*m>=n)
            m--;
        bool yes=0;
        while(m)//枚举m,完全平方因子
        {
            if(ok(m*m))
            {
                yes=1;
                break;
            }
            m--;
        }
        if(yes)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

1003

http://acm.hdu.edu.cn/showproblem.php?pid=4983

解题思路:

gcd(n-a,n)*gcd(n-b,n)=n^k
要求有多少(a,b)满足上面的式子,1<=a,b<=n ,    1<=n,k<=10^9
gcd(n-a,n)<=n , gcd(n-b,n)<=n ,所以gcd(n-a,n)*gcd(n-b,n)<=n^2
当n=1时,只有(1,1)满足式子
当k>2时,有0个(a,b)满足式子
当k=2时,gcd(n-a,n)=n,gcd(n-b,n)=n, 只有(n,n)这种情况满足
当k=1时,gcd(n-a,n)*gcd(n-b,n)=n,也就是 gcd(n-a,n),gcd(n-b,n)均为n的因子
令gcd(n-a,n)=x,即x为n的一个因子
gcd(n-a,n)=x, gcd((n-a)/x, n/x)=1, 满足条件的(n-a)/x也就是 n/x的欧拉函数
所以枚举n的因子,两个因子的欧拉函数相乘,再累加就可以了,注意当x!=n/x时,欧拉函数相乘再*2
,因为a,b两个值可以倒换位置。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int n,k;
ll cnt;

int eular(int n)
{
    int ans=n;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            ans-=ans/i;
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1) ans-=ans/n;
    return ans;
}

int main()
{
    while(rd2(n,k)!=EOF)
    {
        if(n==1||k==2)//注意这个语句和下面的if不能调换位置,
        {
            printf("1\n");
            continue;
        }
        if(k>2)
        {
            printf("0\n");
            continue;
        }
        ll ans=0;
        for(int i=1;i<=sqrt(1.0*n);i++)
        {
            if(n%i==0)
            {
                if(i!=(n/i))
                    ans+=eular(n/i)*eular(i)*2%mod;
                else
                    ans+=eular(n/i)*eular(i)%mod;
            }
        }
        printf("%I64d\n",ans%mod);

    }
    return 0;
}



[BestCoder] Round #6