传送门
小P今天要去金龙小学对 n(1 <= n <= 100)位学生进行英语口语测试,这场口语测试是这样进行的:
1 . 每名学生排好队,按编号1,2,3…n依次进行测试(即1结束考试后,2再考试…);
2. 编号为 i 的学生会使用第 i 套口语测试试题,而每套试题都有规定的时间 ti(1 <= ti <= 100)作答;
3. 每名学生抽到试题后有两个反应:①觉得这题目太难了,立马放弃走人了,没有浪费一分一秒,对于这种小P都会打不合格;②老老实实在这套试题规定的时间 ti 完成口语测试,然后小P会给他一个至少合格分数再走人;
学生们都严格按照抽到的次序进行测试,且没有中断测试的情况。
但是现在这次测试的测试时间被压缩为M分钟(max(ti) <= M)
你的任务是计算:对于每一位学生 i ,为了让学生 i 拿到了合格分数,请计算出学生 i 前面最少有多少人要不合格的才能使得学生i合格。
输出描述
输入包含2行。
第一行,给出两个数 n 和 M(含义和范围已在题面给出),第二行给出 n 个数,其中第i个数表示第i个套题规定时间为 ti 分钟。
输入描述
输入保证每个 ti 都小于 M
输出仅一行,n个数,第i个数表示为了使第 i 个人拿到合格分数,前面最少的不及格的人数。
示例:
Input:
7 15
1 2 3 4 5 6 7
Output:
0 0 0 0 0 2 3
Input:
5 100
80 40 40 40 60
Output:
0 1 1 2 3
说明/提示:
样例一,让前5个学生都做完题目所需要的时间都小于或等于M,所以,他们都不需要不及格的人,所以最少的 不及格人数是0。而为了让第6和第7个学生通过测试,前面分别必须让第3,4和第2,5,6个学生不及格。
问 题 转 换 成 对 于 每 一 个 学 生 i, 删 掉 最 少 的 数 使 得
t1+t2+….ti-1 <= M-ti ,也可转换成在 t1,t2,……ti-1中选择尽
量多的数使得和小于等于 M-ti 。
注意本题一重要条件 1 <= ti <= 100, 范围足够小可以统计每个 i 前面出现了那些数字,然后尽量先取小的数字。
#include
#include
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int i,j,cnt=0,n,m,tmp;
scanf("%d%d",&n,&m);
int a[1000],b[1000],sum[1000];
sum[0]=0;
for(i=1; i<=n; i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
sum[i]=sum[i-1]+a[i];
}
printf("%d ",cnt);
for(i=2; i<=n; i++)
{
cnt=0;
sort(b+1,b+i,cmp);
for(j=1; j<=i; j++)
{
if(sum[i]>m)
{
sum[i]-=b[j];
cnt++;
}
}
printf("%d ",cnt);
}
return 0;
}
传送门
巴德利星球最近举行了足球杯总决赛。整场比赛中,裁判出示了n张黄牌。
比赛一开始,在第一队中有a1个球员,而在第二队中有a2个。
在巴德利星球, 把人罚下场的规则与正常规则是不同的。
来自第一队的一个球员收到k1 张黄牌,他被罚下场并不能继续参加比赛了;
来自第二队的球员则需要 k2 张才会下场。下场的球员不能再收到黄牌。即使某一队(甚至两队)的球员全部被罚下场,比赛仍能继续。
裁判忘记了自己把每张黄牌罚给了谁,所以请你帮助裁判确定可能的被罚下场的人数的最小值和最大值。
输入描述:
共有5行,每行一个整数a1,a2,k1,k2,n。含义如上文所述。
保证:1 ≤ a1,a2,k1,k2 ≤ 1000,1 ≤ n ≤ a1∗k1+a2∗k2;
输出描述:
一行两个整数,表示可能的被罚下场的球员数的最小值和最大值。
示例:
Input:
2
3
5
1
8
Output:
0 4
Input:
3
1
6
7
2
5
Output:
4 4
Input:
6
4
9
10
89
Output:
5 9
贪心思想;
如何考虑最少人数,让每个人都背上最多但不会被罚下的黄牌,例如 k1 = 5,k2 = 6 时,让一队所有人都背上 4 张黄牌,二队每个人都背上 5 张,如果黄牌已经分完,最少人数为 0,否则剩下几张黄牌就最少罚下几个人;
如何考虑最多人数,先把 k 较小的那一队的人罚下,还有黄牌剩
下,再去罚 k 较大的一方。
#include
#define ll long long
int main()
{
ll a,b,k1,k2,n;
ll min,max,ans1=0,ans2=0;
scanf("%lld%lld%lld%lld%lld",&a,&b,&k1,&k2,&n);
min=n,max=n;
min=min-(a*(k1-1)+b*(k2-1));
if(min>0)
ans1=min;
else ans1=0;
if(k1<k2)
{
if(max>(a*k1))
{
ans2+=a;
max -= a*k1;
}
else
{
ans2+=max/k1;
max-=max/k1 * k1;
}
if(max/k2) ans2+=max/k2;
}
else
{
if(max>(b*k2))
{
ans2+=b;
max -= b*k2;
}
else
{
ans2+=max/k2;
max-=max/k2 * k2;
}
if(max/k1) ans2+=max/k1;
}
printf("%lld %lld",ans1,ans2);
return 0;
}
传送门
你在给你的两个妹妹分糖果,已知你口袋里有n颗糖果,每个糖果都有一个序号,序号分别为1 ~ n;
第一个妹妹喜欢序号为a的倍数的糖果,如果你把一颗序号为a的倍数的糖果分给第一个妹妹,第一个妹妹对你的好感度会上升x;
而第二个妹妹则喜欢序号为b的倍数的糖果,如果你把一颗序号为b的倍数的糖果分给第二个妹妹,第二个妹妹对你的好感度会上升y;
你能得到的两妹妹对你好感度之和最大是多少?
输入描述:
输入仅一行,5个正整数n, a, b, x , y (1<= n,a,b,x,y <= 10^9)
输出描述:
输出仅一行一个整数:ans,代表你能得到的最大的两妹妹的好感度之和
示例:
Input
5 2 3 12 15
Output
39
Input
20 2 3 3 5
Output 51
当x 只是 a 的倍数时,分给第一个妹妹;
当x 只是 b 的倍数时,分给第二个妹妹;
既是 a 的倍数又是 b 的倍数时,分给好感度会上升较多的妹妹,
判断既是 a 的倍数又是 b的倍数,用k*lca(a,b)(k = 1,2……)
#include
#define ll long long
ll gcd(ll a, ll b)
{
return b?gcd(b,a%b):a;
}
int main()
{
ll n,a,b,x,y;
ll ans=0;
scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&x,&y);
ll cnt1=n/a;
ll cnt2=n/b;
ll cnt3=n/(a*b/gcd(a,b));
ans+=x*(cnt1-cnt3)+y*(cnt2-cnt3);
if(x>y)
{
ans+=x*cnt3;
}
else ans+=y*cnt3;
printf("%lld",ans);
return 0;
}
传送门
小 M 有两段长度相等的密文 s 和密文 t 。
两个密文都由小写字母“a”和“b”组成的字符串。
密文没被翻译,因此小M不知道密文的信息;
于是小M去查阅了资料,发现让这两个密文 s 和 t 相等就能翻译出里面的内容。
在翻译时可以执行以下任意次数的操作 :
在密文 s 中选择 pos1 (密文 s 中任意一个字母的下标),
在密文t中选择 pos2 (密文 t 中任意一个字母的下标),
并将密文 s 的pos1与密文 t 的 pos2 交换。
现在小M想请你帮他完成翻译的工作,请你输出最少的操作步数以及你的操作序列,你必须使得两串依次执行了你的操作序列后 s 和 t 相等,或者请你表明不可能使这些字符串相等。 (如果有多种操作序列都是最少步数的,你只需要输出其中任意一种)
输出描述:
第一行包含一个整数 n (1 ≤ n ≤ 2 * 10 ^ 5)代表 s 和 t 的长度。第二行是一个包含了n个由“a”和“b”组成的字符串代表密文 s。第三行是一个包含了 n 个由“a” 和 “b” 组成的字符串代表密文 t。
输出描述:
如果不可能使这些字符串相等,则输出 -1。否则,在第一行中打印 k 表示使字符串相等所需的最小操作数。
在接下来的每k行中,打印两个整数:字符串s中的下标和字符串t中的下标,它们应该用于相应的交换操作。
示例:
Input:
4
abab
aabb
Output:
2
3 3
3 2
Input:
8
babbaabb
abababaa
Output:
3
2 6
1 3
7 8
Input:
1
ab
Output:
-1
如果a的数目和b的数目中有一个是奇数, 那么不可能使这两个字符串相等。
先看一般的情况
aa bb a
aa aa a
中间4个字母都需要进行交换, 可以 3 和 4 交换;
此时可以发现这两个都是(b 和 a) 不同, 两个ba不同的下标进行了交换,这里ba不同的数目为2。
同理,ba不同的数目为4、6等偶数时,也能通过ba数目/2次交换使字母相等。
同理,ab不同的数目为2、4、6等偶数时, 也能通过ab数目/2次交换时字母相等。
再看不一般的情况
aa bbba b
aa aaab a
此处ba数目和ab数目都是奇数,
(易知当一种不同的数目是奇数时,另外一种不同的数目也是奇数,因为ab数目都是偶数)
此时只需要交换一组ba的上下顺序即可变成上面的情况,交换任意一组都可以,下面代码选择交换最后一组ab。
#include
#include
using namespace std;
const int MAXN = 2e5 +10;
char a[MAXN], b[MAXN];
vector<int> cnta;
vector<int> cntb;
int main() {
int cnt[100] = {0};
int n, ans = 0; scanf("%d", &n);
scanf("%s%s", a + 1, b + 1);
for (int i = 1; i <= n; ++i)
{
++cnt[a[i]];
}
for (int i = 1; i <= n; ++i)
{
++cnt[b[i]];
}
if (cnt['a'] % 2 || cnt['b'] % 2)
{
printf("-1");
}
else {
for (int i = 1; i <= n; ++i) {
if (a[i] == b[i])
continue;
if (a[i] == 'a')
cnta.push_back(i);
else cntb.push_back(i);
}
if (cnta.size() % 2) {
cnta.insert(cnta.begin(), 2, cnta.back());
cntb.push_back(cnta.back());
cnta.pop_back();
printf("%d\n", (cnta.size() + cntb.size()) / 2);
vector<int>::iterator it = cnta.begin();
for (; it != cnta.end(); ++it) {
printf("%d", *it);
++it;
printf(" %d\n", *it);
}
for (it = cntb.begin(); it != cntb.end(); ++it) {
printf("%d", *it);
++it;
printf(" %d\n", *it);
}
}
return 0;
}
传送门
数学家哥谷奥拉切诺德里发明了一种新的数学运算:◑,而这个运算只能对数位上仅包含0 ~ 2的非负整数进行;
例如 11120 ◑ 2122 = 10212; ◑ 是怎样运算的呢?
首先两数位上仅包含0~2的非负整数按低位对齐,若两数长度不一样,较小的数高位补零,然后相同的位置的两个数字进行不进位加法并对 3 取余数;
再例如:1212 ◑ 2222 = 101,2021 ◑ 11 = 2002 , 11 ◑ 22= 0 …
现在有这样的一条等式 a ◑ b = n;
已知 n 是以2开头并且其他数位都只包含0,1,2的非负整数,请你找出一对(a, b)满足上列等式,并且使得max (a , b) 最小( max ( x , y) 即取 x 和 y 之间的较大值 )
输入描述:
第一行为样例数 T (1 <= T <= 100)
接下来有 2 * T 行,每个样例第一个正整数x;(1 <= x <= 5* 10^4) n是一个以2开头的正整数,它的长度为x
输出描述:
对于每一个n,输出a,b,a和b分别独占一行,要求a ◑ b = n,且使得max(a,b)是最小的;
示例:
input
4
5
22222
5
21211
1
2
9
220222021
output
11111
11111
11000
10211
1
1
110111011
110111010
从高位开始分,
对于 0 分成 0 和 0,
对于 1 只能 1 和 0,
对于2,有两种选择:分成 1 和 1,或者 2 和 0;
当前面出现了 1 时,用 2 和 0,即从高位开始一直均分到 a 和 b,如果出现了 1 就只能一个分到大的数字一个分到小的数字,
假设 a 分到了 1,b 分到了 0,那么后面遇到 1 就把 1 分给 b,0分给 a,遇到 2 就把 2 分给 b,0 分给 a,因为 a 的高位已然大于b,b 的低位无论怎么大都不可能大于 a,因此把大的数字都分给 b 可使最大值 a 最小。
#include
#include
int main()
{
int i,t,n,cnt;
char c[50005],a[50005],b[50005];
scanf("%d",&t);
while(t--)
{
cnt=1;
scanf("%d",&n);
getchar();
scanf("%s",c);
for(i=0; i<n; i++)
{
if(c[i]-'0'==0)
a[i]=48,b[i]=48;
else if(c[i]-'0'==1)
{
if(cnt==1)
a[i]=49,b[i]=48;
else a[i]=48,b[i]=49;
cnt++;
}
else
{
if(cnt==1)
a[i]=49,b[i]=49;
else a[i]=48,b[i]=50;
}
}
a[n]=b[n]='\0';
printf("%s\n%s\n",a,b);
}
return 0;
}
传送门
小A喜欢小B,而小B喜欢小C,但是小C又喜欢小A。
这种复杂的关系我们称为三角恋,现在有n个人,编号为1 ~ n,且你知道他们每一个人喜欢的人是谁( i 喜欢的人不可能是自己,且 i 喜欢的人编号一定为 1~ n ),你能判断出他们之间有没有三角恋关系吗?
输入描述:
第一行有一个正整数n(2 <= n <= 5000),表示有n个人;
第二行为n个整数 F1,F2,…,Fn,(1 <= Fi <= n,Fi != i )表示编号为 i 的人喜欢编号为 Fi 的人。
输出描述:
若他们之间有三角恋关系,请输出YES,否则输出NO
示例:
input
5
2 4 5 1 3
output
YES
input
5
5 5 5 5 1
output
NO
本题判断该有向图中有无三元环,但一个点只指向一个点,且没有自己指向自己的情况出现,只需判断有无F[F[F[i]]] == i 即可。
#include
int main()
{
int n,i,x,y,z,a[5005],flag=1;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
{
x=a[i];
y=a[x];
z=a[y];
if(z==i)
flag=0;
}
if(flag==0)printf("YES");
else printf("NO");
return 0;
}
传送门
你将得到一个带有前导零的01串,现在小A想得到一个所有1都连在一起的 01串;而你能进行的操作是在 01串中删去一个 0;
问,你最少进行几次操作可满足小A的要求?
输入描述:
第一行为样例数 T ,(1 <= T <= 100);
接下来有 T 行,每行一个可能带有前导0的01串,长度不超过100;
输出描述:
对于每个样例输出你的最少操作数量
示例:
input
3
010011
0
1111000
output
2
0
0
去掉头尾的 0 后统计剩下的串出现了几个 0。
#include
#include
int main()
{
int i,j,t,ans,start=0,end=0;
char a[150];
scanf("%d",&t);
while(t--)
{
ans=start=end=0;
scanf("%s",a);
for(i=0; i<strlen(a); i++)
{
if(a[i]-'0'==1)
{
start=i;
break;
}
}
for(j=strlen(a)-1; j>=0; j--)
{
if(a[j]-'0'==1)
{
end=j;
break;
}
}
for(i=start; i<end; i++)
{
if(a[i]-'0'==0)
ans++;
}
printf("%d\n",ans);
}
return 0;
}
传送门
小P今天要去金龙小学对 n(1 <= n <= 100)位学生进行英语口语测试,这场口语测试是这样进行的:
1 . 每名学生排好队,按编号1,2,3…n依次进行测试(即1结束考试后,2再考试…);
2. 编号为 i 的学生会使用第 i 套口语测试试题,而每套试题都有规定的时间 ti(1 <= ti <= 100)作答;
3. 每名学生抽到试题后有两个反应:①觉得这题目太难了,立马放弃走人了,没有浪费一分一秒,对于这种小P都会打不合格;②老老实实在这套试题规定的时间 ti 完成口语测试,然后小P会给他一个至少合格分数再走人;
学生们都严格按照抽到的次序进行测试,且没有中断测试的情况。
但是现在这次测试的测试时间被压缩为M分钟(max(ti) <= M)
你的任务是计算:对于每一位学生 i ,为了让学生 i 拿到了合格分数,请计算出学生 i 前面最少有多少人要不合格的才能使得学生i合格。
输出描述
输入包含2行。
第一行,给出两个数 n 和 M(含义和范围已在题面给出),第二行给出 n 个数,其中第i个数表示第i个套题规定时间为 ti 分钟。
输入描述
输入保证每个 ti 都小于 M
输出仅一行,n个数,第i个数表示为了使第 i 个人拿到合格分数,前面最少的不及格的人数。
A题的题面,其他不变,ti范围改成1 <= ti <= 1e9
#include
#include
#include
typedef long long ll;
using namespace std;
const int maxn = 2e5+10;
int n, t;
ll sum[maxn*4], num[maxn*4], a[maxn], b[maxn],m;
void update(int rt, int l, int r, int x)
{
if(l == r)
{
sum[rt] += b[x];
num[rt] ++;
return;
}
int mid = (l + r) / 2;
if(x <= mid) update(rt * 2,l,mid, x);
if(x > mid) update(rt * 2 + 1,mid+1,r, x);
sum[rt] = sum[rt*2] + sum[rt*2+1];
num[rt] = num[rt*2] + num[rt*2+1];
}
int query(int rt, int l, int r, ll ans)
{
if(l == r)
{
return ans / b[l];
}
int mid = (l + r)/ 2;
if(ans <= sum[rt*2]) return query(rt * 2,l,mid, ans);
else return num[rt*2] + query(rt * 2 + 1,mid+1,r, ans - sum[rt*2]);
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d %lld", &n, &m);
for(int i = 1 ; i <= n ; ++ i)
{
scanf("%lld", &a[i]);
b[i] = a[i];
}
sort(b+1, b+1+n);
int len = unique(b+1, b+1+n) - b - 1;
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
ll res = 0;
for(int i = 1 ; i <= n ; ++ i)
{
res += a[i];
int ans = i-1;
int id = lower_bound(b+1, b+1+len, a[i]) - b;
if(res > m) ans = query(1, 1, len, m - a[i]);
update(1, 1, len, id);
printf("%d ",i-ans-1);
}
printf("\n");
}
return 0;
}