传送门
用火柴棍表示加法等式,等式要符合数学运算,1用一根火柴,8用8根。给你n根火柴根,问能构成等式所需火柴根还差多少。n可以不够,但是一定要用完。问还需要的火柴根的最小值。
输入q组询问,每组输入n根火柴
输出还需要火柴根数的最小值
我们可以列一个等式a+b=(a+b),所需要的火柴根数为a+b+(a+b),即2(a+b),一定是一个偶数。
也就是说,对于n来说,若n是偶数(且n大于2,n为2的时候答案就是2),不需要额外的火柴就可以构成一个等式;若n是奇数(题中输入时候n大于1),只需要再加一根就可以构成偶数根火柴。
答案就很明确了。
#include<stdio.h>
int main()
{
int q,n;
scanf("%d",&q);
while(q--)
{
scanf("%d",&n);
if(n<=3)
printf("%d\n",4-n);
else
printf("%d\n",n%2);
}
return 0;
}
给两个字符串,分别是s和t,对于相邻的两个字符,可以进行赋值操作,如把a1的值赋给a2,或者把a2的值赋给a3。题中有很关键的一点是,对两个字符串都可以进行操作,问两个字符串经过若干次操作后是否能变成相同的字符串。
输入q,表示q次询问,每次询问输入两个字符串,分别是s和t。
对于每次输出,输出“YES”或者“NO”。题中说明,输出格式不限,用“YES”举的例子,我的理解是,对于“YES”和“NO”,大小写都无所谓。但是我都输出小写的时候,答案是错误的,但我把答案改成了都是大写就对了。
这道题只需要保证两个字符串中有一个单词相同就可以了。因为对于每一个字符串来说,可以经过若干次操作,把整个字符串变为只有一个字符构成的字符串。所以,只要有一个相同的字符就可以了。我选择用一个数组a【26】来存储s中出现的所有字母,只要有一个相同,那么就可以退出循环结束。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,flag;
string s,t;
scanf("%d",&n);
while(n--)
{
flag=0;
int a[28]={0};
cin>>s;
cin>>t;
int len=s.size();
int i,temp;
for(i=0;i<len;i++)
{
a[s[i]-'a']=1;
}
for(i=0;i<len;i++)
{
if(a[t[i]-'a']==1)
{
flag=1;break;
}
}
if(flag==1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
输入q个询问,n表示有几张票,下面输入n个票价,然后输入x和a、y和b,k。表示从排名为a的倍数的票中抽取票价的x%,表示从排名为b的倍数的票中抽取票价的y%,问抽取总数是否能大于等于k。如果不能大于,输出-1;如果能大于,输出抽取票的最小数量。
注意:此处的抽取票数,是指从第一张开始,直到最后一个提取票价的为止。
首先,我们可以看得出,因为票的顺序是可以改变的,所以我们可以调整顺序使得价值序号为a和b的公倍数的票价值最大,如果x大于y,那么让序号为a的票的价值最大,再从剩余的中挑选最大的给b。在此基础上,我们要用二分法查找答案,这样会快一些。利用前缀和查找答案可以把时间复杂度降至O(n)
注意数据范围
关于二分法的介绍,这一篇博客比较好,推荐一下。
浅谈二分答案
我自己调了一个程序,但是一直有问题,只好从网上摘了一个,他的代码没有注释,我加几点注释,以便大家阅读。
代码出处
#include
using namespace std;
typedef long long LL;
const int MAXN = 2e5+10;
int Val[MAXN];
LL Sum[MAXN];
LL n, x, y, a, b, lcm;
LL k;
bool Check(int mid)
{
int cnta = mid/a;//在卖的mid张票中,为a的倍数的票有cnta张
int cntb = mid/b;//在卖的mid张票中,为b的倍数的票有cntb张
int cnts = mid/lcm;//在卖的mid张票中,为a和b的公倍数的票有cnts张
cnta -= cnts, cntb -= cnts;//我觉得这一步可有可无
LL sum = 0;
sum += (Sum[cnts]/100)*(x+y);//把最有价值的留给公倍数
sum += ((Sum[cnts+cnta]-Sum[cnts])/100)*x;//计算只抽取x%的
sum += ((Sum[cnts+cnta+cntb]-Sum[cnts+cnta])/100)*y;//计算只抽取y%的
if (sum >= k)//能否达到目标
return true;
return false;
}
int main()
{
ios::sync_with_stdio(false);//加快运行速度
cin.tie(0);//提高cin输入流运行速度
int t;
cin >> t;
while (t--)
{
cin >> n;
for (int i = 1;i <= n;i++)
cin >> Val[i];
cin >> x >> a;
cin >> y >> b;
cin >> k;
if (x < y)
swap(x, y), swap(a, b);//保证x永远比y大
sort(Val+1, Val+1+n, greater<int>());//对票价进行排序,按照从高往低排序
Sum[0] = 0;
for (int i = 1;i <= n;i++)
Sum[i] = Sum[i-1]+Val[i];//计算前i个票价总和,记录在sum中
lcm = (a*b)/__gcd(a, b);//求a和b的最小公倍数
int l = 1, r = n, res = n+1;//l是左标记,r是右标记,res表示需要卖的最小票数
while (l <= r)//二分查找
{
int mid = (l+r)/2;//先假设卖mid张票就够了
if (Check(mid))//如果够了的话
{
res = min(res, mid);//更新需要卖的最小票数
r = mid-1;//看看卖mid/2张可不可以
}
else
l = mid+1;//如果不行就多卖几张
}
if (res == n+1)//全卖了也不行
puts("-1");
else
printf("%d\n", res);
}
return 0;
}