【codeforces #299(div 1)】ABC题解

A. Tavas and Karafs

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Karafs is some kind of vegetable in shape of an 1 × h rectangle. Tavaspolis people love Karafs and they use Karafs in almost any kind of food. Tavas, himself, is crazy about Karafs.

Each Karafs has a positive integer height. Tavas has an infinite 1-based sequence of Karafses. The height of the i-th Karafs is si = A + (i - 1) × B.

For a given m, let’s define an m-bite operation as decreasing the height of at most m distinct not eaten Karafses by 1. Karafs is considered as eaten when its height becomes zero.

Now SaDDas asks you n queries. In each query he gives you numbers l, t and m and you should find the largest number r such that l ≤ r and sequence sl, sl + 1, …, sr can be eaten by performing m-bite no more than t times or print -1 if there is no such number r.

Input
The first line of input contains three integers A, B and n (1 ≤ A, B ≤ 106, 1 ≤ n ≤ 105).

Next n lines contain information about queries. i-th line contains integers l, t, m (1 ≤ l, t, m ≤ 106) for i-th query.

Output
For each query, print its answer in a single line.

Sample test(s)
input
2 1 4
1 5 3
3 3 10
7 10 2
6 4 8
output
4
-1
8
-1
input
1 5 2
1 5 10
2 7 4
output
1
2

思路题。

首先二分答案,如何判定答案是否可行呢?

要满足两个条件:
①最大值 t
summt

这两个条件的必要性是显然的,来证明充分性:
假设 m,t 能满足的状态叫做 (m,t) 状态,我们递归的来看。

如果满足上述两个条件的是 (m,t) 状态,那么我进行一次操作必然会到达 (m,t1) 状态,证明分两种情况:
A.当前 >0 的个数 >m ,进行一次操作必然满足后者;
可是如果最大值有多个进行1次操作后会不会还有剩余呢?必然不会。因为 summt =t 的必然不会超过 m

B.当前>0的个数 m ,进行一次操作必然满足前者;
而此时最大值 <t <script type="math/tex" id="MathJax-Element-3603"> m sum 必然小于 m(t1)

于是我们一直递归下去,就会到达 (m,0) 状态,满足上面两个条件这个状态必然是合题意的,递归返回之后就证明了 (m,t) 状态是合题意的。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define LL long long
using namespace std;
int A,B,n,l,T,m;
LL x,t;
int ok(LL k)
{
    LL la=1LL*(k-1)*B+(LL)x;
    if (la>(LL)T) return 0;
    if ((la+x)*k/2LL<=t) return 1;
    return 0;
}
int main()
{
    scanf("%d%d%d",&A,&B,&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&l,&T,&m);
        x=A+1LL*(l-1)*B;
        if ((LL)T<x)
        {
            puts("-1");
            continue;
        }
        t=1LL*T*m;
        LL L=1,R=(LL)1e6,ans=0;
        while (L<=R)
        {
            LL M=(L+R)>>1LL;
            if (ok(M)) ans=M,L=M+1;
            else R=M-1;
        }
        printf("%d\n",(int)(l-1+ans));
    }
    return 0;
}

B. Tavas and Malekas

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Tavas is a strange creature. Usually “zzz” comes out of people’s mouth while sleeping, but string s of length n comes out from Tavas’ mouth instead.

Today Tavas fell asleep in Malekas’ place. While he was sleeping, Malekas did a little process on s. Malekas has a favorite string p. He determined all positions x1 < x2 < … < xk where p matches s. More formally, for each xi (1 ≤ i ≤ k) he condition sxisxi + 1… sxi + |p| - 1 = p is fullfilled.

Then Malekas wrote down one of subsequences of x1, x2, … xk (possibly, he didn’t write anything) on a piece of paper. Here a sequence b is a subsequence of sequence a if and only if we can turn a into b by removing some of its elements (maybe no one of them or all).

After Tavas woke up, Malekas told him everything. He couldn’t remember string s, but he knew that both p and s only contains lowercase English letters and also he had the subsequence he had written on that piece of paper.

Tavas wonders, what is the number of possible values of s? He asked SaDDas, but he wasn’t smart enough to solve this. So, Tavas asked you to calculate this number for him.

Answer can be very large, so Tavas wants you to print the answer modulo 109 + 7.

Input
The first line contains two integers n and m, the length of s and the length of the subsequence Malekas wrote down (1 ≤ n ≤ 106 and 0 ≤ m ≤ n - |p| + 1).

The second line contains string p (1 ≤ |p| ≤ n).

The next line contains m space separated integers y1, y2, …, ym, Malekas’ subsequence (1 ≤ y1 < y2 < … < ym ≤ n - |p| + 1).

Output
In a single line print the answer modulo 1000 000 007.

Sample test(s)
input
6 2
ioi
1 3
output
26
input
5 2
ioi
1 2
output
0
Note
In the first sample test all strings of form “ioioi?” where the question mark replaces arbitrary English letter satisfy.

Here |x| denotes the length of string x.

Please note that it’s possible that there is no such string (answer is 0).

hash/kmp

这题的基本思路就是判断重叠部分是否满足要求。

hash:
求出相应部分的哈希值来判断即可。

kmp:
先把字符串确定出来(重叠部分按照先后顺序来确定),用kmp来判断是否在读入的每个位置都能够匹配。

我用的是前者。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define mod 1000000007
#define LL long long
#define M 1000005
using namespace std;
char p[M];
int n,m,x[M],l,ne[M];
LL po[M],pre[M];
void kmp()
{
    int j=0;
    for (int i=2;i<=l;i++)
    {
        while (j&&p[i]!=p[j+1]) j=ne[j];
        if (p[i]==p[j+1]) j++;
        ne[i]=j;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",p+1);
    l=strlen(p+1);
    //kmp();
    pre[l+1]=0;
    po[0]=1;
    for (int i=1;i<=l;i++)
        po[i]=po[i-1]*137LL%mod;
    for (int i=l;i;i--)
        pre[i]=(pre[i+1]+(p[i]-'a'+1)*po[l-i]%mod)%mod;
    LL ans=1;
    for (int i=1;i<=m;i++)
        scanf("%d",&x[i]);
    int L=0,ok=1;
    for (int i=1;i<=m;i++)
    {
        while (L+1<x[i])
            L++,ans=1LL*ans*26%mod;
        if (i!=1&&x[i-1]+l-1>=x[i])
        {
            int k=x[i-1]+l-1-x[i]+1;
            if (((pre[1]-pre[k+1]+mod)%mod)!=(pre[l-k+1]*po[l-k]%mod)) ok=0;
        }
        if (!ok) break;
        L=x[i]+l-1;
    }
    while (L+1<=n)
        L++,ans=1LL*ans*26%mod;
    cout<<(ok*ans%mod+mod)%mod<<endl;
    return 0;
}

C. Tavas and Pashmaks

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Tavas is a cheerleader in the new sports competition named “Pashmaks”.

This competition consists of two part: swimming and then running. People will immediately start running R meters after they finished swimming exactly S meters. A winner is a such person that nobody else finishes running before him/her (there may be more than one winner).

Before the match starts, Tavas knows that there are n competitors registered for the match. Also, he knows that i-th person’s swimming speed is si meters per second and his/her running speed is ri meters per second. Unfortunately, he doesn’t know the values of R and S, but he knows that they are real numbers greater than 0.

As a cheerleader, Tavas wants to know who to cheer up. So, he wants to know all people that might win. We consider a competitor might win if and only if there are some values of R and S such that with these values, (s)he will be a winner.

Tavas isn’t really familiar with programming, so he asked you to help him.

Input
The first line of input contains a single integer n (1 ≤ n ≤ 2 × 105).

The next n lines contain the details of competitors. i-th line contains two integers si and ri (1 ≤ si, ri ≤ 104).

Output
In the first and the only line of output, print a sequence of numbers of possible winners in increasing order.

Sample test(s)
input
3
1 3
2 2
3 1
output
1 2 3
input
3
1 2
1 1
2 1
output
1 3

转化+计算几何+单调栈。

首先设 k=1ri,b=1si ,问题就转化为是否存在 x y使得 kix+biy 不大于任何的 kjx+bjy ,同时➗y,这道题就变成了【BZOJ 3190】

完全一样的思路,但是要注意这道题卡精度,所以中间的计算要用分数同分来算,不要出现小数。

题解中的做法是把 (1ri,1si) 看成一个个的点,用这些点求凸包,答案就是凸包上从最左到最下(逆时针)的所有点。

为什么呢?

(R,S) 看做向量,每个人所用的时间就是他们所代表的点 (1ri,1si) 与这个向量点乘的结果,也就是在这个向量上的投影,那么凸包里面的肯定不如凸包外面的优,右上的肯定不如左下的优。

我的代码是前者。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define M 200005
#define LL long long
using namespace std;
int ok[M],n,q[M],s[M];
struct data
{
    int id,a,b;
}c[M];
bool cmp(data a,data b)
{
    if (a.a==b.a) return a.b>b.b;
    return a.a>b.a;
}
int Judge(data a,data b,data c)
{
    LL k=1LL*(b.a-a.a)*(c.a-b.a);
    if (k<0) k=-1;
    else k=1;
    if (1LL*(a.b-b.b)*a.a*c.b*(c.a-b.a)*k>1LL*k*(b.b-c.b)*c.a*a.b*(b.a-a.a))
        return 1;
    return 0;
}
int interisminus(data a,data b)
{
    int x=1,y=1;
    if (a.b<b.b) x=-1;
    if (a.b==b.b) x=0;
    if (b.a<a.a) y=-1;
    if (x*y!=1) return 1;
    return 0;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d%d",&c[i].a,&c[i].b),
        c[i].id=i;
    sort(c+1,c+1+n,cmp);
    int r=0;
    c[0].a=-1;
    for (int i=1;i<=n;i++)
    {
        if (c[i].a==c[i-1].a) continue;
        while (r>1&&Judge(c[i],c[q[r]],c[q[r-1]]))
            r--;
        q[++r]=i;
    }
    while (r>1&&interisminus(c[q[r]],c[q[r-1]]))
        r--;
    for (int i=1;i<=r;i++)
        ok[c[q[i]].id]=1;
    /*for (int i=r;i>1;i--)
    {
        if (c[q[i]].b<=c[q[i-1]].b) ok[c[q[i]].id]=0;
        else break;
    }*/
    for (int i=2;i<=n;i++)
        if (c[i].a==c[i-1].a&&c[i].b==c[i-1].b&&ok[c[i-1].id])
            ok[c[i].id]=1;
    for (int i=1;i<=n;i++)
        if (ok[i])
            printf("%d ",i);
    printf("\n");
    return 0;
}

写通分的时候一定要细心,否则就会这样TAT
这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值