第一题:http://acm.hdu.edu.cn/showproblem.php?pid=5776
解题思路:
维护前缀和,然后枚举m的倍数,在利用哈希去找即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int maxn = 100005;
int n,m,sum[maxn],a[maxn];
map<int,int> Map;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
Map.clear();
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
bool flag = false;
int cnt = 0;
Map[sum[0]] = ++cnt;
for(int i = 1; i <= n && !flag; i++)
{
sum[i] = sum[i-1] + a[i];
int k = 1;
while(k * m <= sum[i])
{
int tmp = sum[i] - k * m;
if(Map.find(tmp) != Map.end())
{
flag = true;
break;
}
k++;
}
Map[sum[i]] = ++cnt;
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
第二题:http://acm.hdu.edu.cn/showproblem.php?pid=5777
解题思路:
距离越远,就越要用那k-1次去推,最后用1次把所有都推了就好了,所以是先sort一遍,把最大的k-1个去掉即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+7;
int a[N],t,n,k;
int main(){
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(int i=2;i<=n;i++)scanf("%d",a+i);
sort(a+1,a+n+1);
long long ans=n;
for(int i=1;i<=n-k+1;i++)ans+=a[i];
printf("%I64d\n",ans);
}
return 0;
}
第三题:http://acm.hdu.edu.cn/showproblem.php?pid=5778
解题思路:思路:由于y质因数分解式中每个质因数均出现2次,那么y是一个完全平方数,设y=z*z,题目可转换成求z,使得每个质因数出现1次. 我们可以暴力枚举z,检查z是否符合要求,显然当z是质数是符合要求,由素数定理可以得,z的枚举量在logn级别
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const long long INF = 0x7fffffffffffffffll;
long long ans;
long long n;
bool check(long long x)
{
if(x < 2)
return false;
long long t = x;
for(long long i = 2;i * i <= x;i++)
{
if(x % i == 0)
{
if(x % (i * i)==0)//出现了超过一次
{
return false;
}
x /= i;
}
}
ans=min(ans,abs(t*t-n));
return true;
}
int main ()
{
int t;
cin>>t;
while(t--)
{
scanf("%I64d",&n);
long long x=(long long)(sqrt(n * 1.0)+0.5);
int flag = 0;
ans = INF;
for(int i=0;;i++)
{
if(check(x + i))
flag = 1;
if(check(x - i))
flag = 1;
if(flag == 1)
break;
}
printf("%I64d\n",ans);
}
return 0;
}