感觉题目不是很难,但比赛时并不能很顺利的切掉,还是太菜了。
记录一下排名吧。比赛只打了一会,所以这次排名50.
A题求k的幂是否能整除n。枚举一下即可。关键是枚举次数为多少。
这里可以借用一下题解的第二个思路,一个数能整除另一个数,那么它的唯一分解式所有数的幂必须不小于另一个数的唯一分解式对应的那个幂。所以最小的质数为2,那么实际上n最大的幂也不会超过
所以我只要枚举
次即可。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d %d",&n,&k);
if(n==1)
{
cout<<0<<endl;
continue;
}
long long now=1;
int t=1;
bool flag=0;
for(int i=1;i<=n;i*=2,t++)
{
now=now*k%n;
if(now==0)
{
flag=1;
break;
}
}
if(flag)
cout<<t<<endl;
else puts("unbounded");
}
}
H题感觉特别好,题解的思路十分显然,但比赛的时候没想清楚,赛后写的时候也wa了好多遍。
我们这样想,你只能保证一部分人能通过,所以最高的分数肯定会给他们,然后其他的分数先会给自己喜欢的,再有多余的会给不喜欢中的能晋级的那几个,还有多余的才会给不喜欢的不能晋级的。而给的分数的逻辑可以贪心去想。
所以二分通过人数,然后再将不喜欢的不能晋级的人中的分数与你想要晋级的最后一名的分数进行比较来判断是否可行即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int k;
int n,s,f;
int fav[maxn],oth[maxn],sco[maxn];
bool check(int num)
{
int minsco=3e6;
for(int i=f,j=k-num+1;i>=f-num+1;i--,j++)
{
if(j<1)minsco=min(minsco,fav[i]);
else minsco=min(minsco,fav[i]+sco[j]);
}
int getoth=k-f;
if(getoth<0)
{
int othnum=s-num;
int idx=(n-f)-othnum;
return oth[idx]<=minsco;
}
int othnum=s-num;
int othout=n-f-othnum;
int j=max(0,getoth-othnum);
for(int i=1;i<=othout;i++,j=max(0,j-1))
if(minsco<oth[i]+sco[j])
return 0;
return 1;
}
void solve()
{
int l=max(0,min(f,s-(n-f)));
int r=min(s,f);
int ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
cout<<ans<<endl;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&n,&s,&f);
for(int i=1;i<=f;i++)
scanf("%d",&fav[i]);
for(int i=1;i<=n-f;i++)
scanf("%d",&oth[i]);
scanf("%d",&k);
for(int i=1;i<=k;i++)
scanf("%d",&sco[i]);
sort(fav+1,fav+1+f);
sort(oth+1,oth+1+n-f);
sort(sco+1,sco+1+k);
solve();
}
return 0;
}