点击:http://oj.acm.zstu.edu.cn/JudgeOnline/contest.php?cid=3650
Problem A: 回文
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1637 Solved: 505
Description
Input
Output
Sample Input
5 abA gg Codeforces acmermca myacm
Sample Output
NO NO NO YES YES
WA了三遍的水题。字符串处理,把题读全了就可以了。我是分的奇偶长度,分别考虑的,这样清晰点
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
char s[600050];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
int len=strlen(s);
if(len==1)
{
printf("NO\n");
continue;
}
int i,j;
if(len%2==0)
{
i=0;
j=len-1;
while(i<j)
{
if(s[i]==s[j])
{
i++;
j--;
}
else break;
}
if(s[0]==s[len-1]&&len>2)
{
printf("YES\n");
}
else printf("NO\n");
}
else
{
i=0;
j=len-1;
while(i<j)
{
if(s[i]==s[j])
{
i++;
j--;
}
else break;
}
if(s[0]==s[len-1])
{
printf("YES\n");
}
else printf("NO\n");
}
}
return 0;
}
Problem I: 约素
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1809 Solved: 469
Description
Input
第一行给测试总数T(T <= 10000)。
接下来有T行,每行有两个数字n(1 <= n <= 1000000000)和p(2 < p <= 1000000000)。Output
每组测试数据输出一行,如果n的约数个数是p,输出“YES”,否则输出“NO”。
Sample Input
5
64 7
911 233
1080 13
1024 11
20170211 1913
Sample Output
YES
NO
NO
YES
NO
题解:暴力求约数,常规技巧简化
约数,我都想问到底什么叫做约数。以前做的计算约数的个数的理解记得不是这样的来。这个题的约数就是让你暴力找一遍n%i==0时i的个数。而紫书上的约数的个数是表示质因子的个数相乘得来的。
当然这个也不能1-n暴力,因为对于n%x==0的话,也就得出了另一个约数:y=n/x,既然是约数,x,y都是小于n的,那么x从1开始一直到,n/x就可以了,此时当x增大的时候,n/x就在减小。知道x>=n/x.特别处理,当x==n/x的时候约数的个数+1,否则+2(x和n/x都是n的约数)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,p;
int sum;
scanf("%d%d",&n,&p);
sum=0;
for(int i=1;i<=n/i;i++)
{
if(n%i==0)
{
sum++;
if(i!=n/i)sum++;
}
}
if(n==1)sum=1;
//cout<<sum<<endl;
if(sum==p)printf("YES\n");
else printf("NO\n");
}
return 0;
}
Problem D: 买iphone
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1719 Solved: 316
Description
Input
Output
Sample Input
10 3 3 3 4 20 7 1 1 1 80 3 100 3 3 15 4 3 5 6
Sample Output
Yes No No Yes
HINT
没想到这个题纯暴力就能过了,当然了不是k^2级别的。一共有k个人去装手机,假设有x个人装a,y(y小于k-x)个人装b,剩下的人装c,只要判断出x*a+y*b+(k-x-y)*c==n的情况就可以了
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,k,a,b,c;
while(~scanf("%d%d%d%d%d",&n,&k,&a,&b,&c))
{
int flag=0;
for(int i=0;i<=k;i++)
{
for(int j=0;j<=k-i;j++)
{
if(a*i+b*j+c*(k-i-j)==n)
{
flag=1;
break;
}
if(flag)break;
}
}
if(flag)printf("Yes\n");
else printf("No\n");
}
return 0;
}
Problem E: 同源数
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1288 Solved: 224
Description
Input
Output
Sample Input
18 12 2 3
Sample Output
Yes No
这个题是分析的时间最长的一个题了,最后想出解法后还因为没考虑到全面的情况,又花了很长的时间。首先读完题目的第一反应就是唯一分解定理,然后就卡壳了。突然想到了gcd(),就在纸上分析了一下,慢慢的才ac的。
同源数,也就是他们的质因子的元素是相同的(个数不一定相同)。假如a=2*3*3*5*7,b=2*2*3*5*5*7,他们两个是同源数,对a,b求gcd(a,b)=g;显然g分解后质因子一定包含他们共有的质因子,即2*3*5*7,然后a,b都除以他们的质因子,如果两个数是同源数的话,那么让a一直除以a和g的gcd(),a=a/gcd(a,g),直到a==1或gcd(g,a)为止,如果a==1的说说明了a的质因子只包含了和g相同的质因子,如果a!=1&&gcd(a,g)==1的话,说明a和g互素,也就是a中的质因子有和g中的质因子不同的元素。同理对b也这样处理。如果a==1&&b==1的话说明是同源数,否则不是。
特殊处理a==b和a==1||b==1的情况。
#include<bits/stdc++.h>
using namespace std;
unsigned long long gcd(unsigned long long a,unsigned long long b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
unsigned long long x,y;
while(~scanf("%lld%lld",&x,&y))
{
if(x==y)
{
printf("Yes\n");
}
else if(x==1&&y!=1)
{
printf("No\n");
}
else if(x!=1&&y==1)
{
printf("No\n");
}
else
{
unsigned long long z=gcd(x,y);
unsigned long long a,b;
a=x/z;
b=y/z;
//cout<<z<<" "<<a<<" "<<b<<endl;
int aa,bb;
aa=1;
bb=1;
while(1)
{
unsigned long long q;
q=gcd(a,z);
a=a/q;
if(a==1)
{
break;
}
if(q==1)
{
aa=0;///不行
break;
}
}
while(1)
{
unsigned long long q;
q=gcd(b,z);
b=b/q;
if(b==1)
{
break;
}
if(q==1)
{
bb=0;///不行
break;
}
}
if(aa&&bb)
{
printf("Yes\n");
}
else printf("No\n");
}
}
return 0;
}
Problem H: 玩具
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 718 Solved: 132
Description
Input
Output
Sample Input
3 5 14 1 2 3 4 5 5 4 3 2 1 3 1 100 1000 10000 100 1000 10000 1 0 1000000 1000000
Sample Output
15 10000 1000000
当读完这个题的时候想到的是0,1背包的变形,但是包太大了,就不在想了。
后来用的线段树的查询,但是超时了,后来补题的时候想到了前i个数的和,那么s[i]-s[j]及时区间i~j的和了,在用RMQ求区间最大值,此时还是用的n^2的区间判断还是超时了。最后用的取尺法来确定一个区间,因为如果大区间合法的话,那么小区间就不用判断了,这样会节省时间。但是在开始的时候把自己RMQ的区间和前缀和的区间弄混了,卡了好久。
#include <bits/stdc++.h>
using namespace std;
int a[5005],b[5005];
int p[5005],happy[5005];
int M[5005*4];
void build(int node,int b,int e,int M[],int a[])
{
if(b==e)M[node]=a[b];
else
{
build(2*node,b,(b+e)/2,M,a);
build(2*node+1,(b+e)/2+1,e,M,a);
if(M[node*2]>=M[2*node+1])M[node]=M[2*node];
else M[node]=M[2*node+1];
}
}
int query(int node,int b,int e,int M[],int i,int j)
{
int p1,p2;
if(i>e||j<b)return 0;
if(b>=i&&e<=j)return M[node];
p1=query(2*node,b,(b+e)/2,M,i,j);
p2=query(2*node+1,(b+e)/2+1,e,M,i,j);
if(p1==0)return p2;
if(p2==0)return p1;
if(p1>=p2)return p1;
return p2;
}
int main()
{
int t,n,K;
scanf("%d",&t);
while(t--)
{
int mx=0;
scanf("%d%d",&n,&K);
p[0]=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
p[i]=p[i-1]+a[i];
}
build(1,1,n,M,a);
happy[0]=0;
for(int j=1; j<=n; j++)
{
scanf("%d",&b[j]);
happy[j]=happy[j-1]+b[j];
}
int l,r;
l=1;///不能设为0,因为我的rmq查询的区间最大值是从l->r的全部值,
///而我的p和happy所包含的p[r]-p[l]是从l+1->r的值
r=1;
while(r<=n)
{
if((p[r]-p[l]+a[l]-query(1,1,n,M,l,r))<=K)
{
//cout<<l<<" "<<r<<" "<<query(1,1,n,M,l,r)<<endl;
mx=max(mx,happy[r]-happy[l]+b[l]);
r++;
}
else
{
while(l<r&&(p[r]-p[l]+a[l]-query(1,1,n,M,l,r))>K)
{
//cout<<l<<" "<<r<<" "<<query(1,1,n,M,l,r)<<endl;
l++;
//mx=max(mx,happy[r]-happy[l]);
}
if((p[r]-p[l]+a[l]-query(1,1,n,M,l,r))<=K)mx=max(mx,happy[r]-happy[l]+b[l]);
if(r==n)break;
}
}
printf("%d\n",mx);
}
return 0;
}