Codeforces Round330 Div2题解

这次太狗血了,进行到一半结果C题有问题unrated了。

A题不写了,比较简单

B. Pasha and Phone
大意就是给长度为n的数,分为n/k部分,即每部分k个digit,所以总共有n/k个k位数。对于第i个数,求能被Ai整除,且不以Bi开头的数的个数。求这个n位数可能的情况。
可以看到总的情况ans = ans1 * ans2 * … ans(n/k)。
分别求每一小部分的可能情况即可, 即求k位数能背中能被A整除又不以B开头的数,其中能被A整除的个数为tot = (10^k - 1)/A + 1,整数除法。以B开头的能被A整除的最小数为 num1 = (B * 10^(k - 1) / A)向上取整 * A,以B开头的能背A整除的最大数为 num2 = ((B+1) * 10^(k - 1) - 1) / A * A,整数除法。如果num1 <= num2,则tot减去(num2 - num1) / A + 1,代码

#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))
#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))
#define LL long long
#define ALL(v) v.begin(),v.end()
#define ZERO(v) memset(v, 0, sizeof v)
#define NEG(v)  memset(v, -1, sizeof v)
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MOD 1000000007
#define PI 3.141592653589793
inline long double min(long double a , long double b) {if(a < b)return a; return b;}
inline long double max(long double a , long double b) {if(a < b)return b; return a;}

int n;
int k;
int b[100100];
int a[100100];
int powTen(int kk)
{
    int res=  1;
    while(kk)
    {
        res *= 10;
        kk--;
    }
    return res;
}
LL solve(int index)
{
    int aa = a[index];
    int bb = b[index];
    int end = powTen(k) - 1;
    end = end/aa * aa;
    int tot = end / aa + 1;
    int start = bb * powTen(k - 1);
    end = (bb + 1) * powTen(k - 1) - 1;
    end = end / aa * aa;
    if(start % aa != 0)
        start = (start / aa + 1) * aa;
    if(end >= start)
    {
        tot -= (end - start) / aa;
        tot--;
    }
    return tot;
}
int main(){

    cin >> n;
    cin >> k;
    FOR(i,0,n/k)
    scanf("%d", &a[i]);
    FOR(i,0,n/k)
    scanf("%d", &b[i]);
    LL res = 1;
    FOR(i,0,n/k)
    {
        res *= solve(i);
        res %= MOD;
    }
    cout << res << endl;
    return 0;
}

C. Warrior and Archer
题目意思是有N个数,A和B每次选一个去除,直到剩2个,A和B都做出最优选择的话最后结果是一定的,问最后两个数之间的距离。
这题比赛的时候是N为任意,但是因为N奇数的时候好像答案有问题,现在重新post出来的时候已经定义N为偶数了,那这样就简单了。
先sort arr,然后设P=min{arr[i + n / 2] - arr[i]}。我们设最后的结果为ans,然后证明P即为ans。因为首先很显然P是小于等于ans的,假设arr[I + n / 2] - arr[I] == P,则对于warrior来说,他只要保证将j < I 以及 j > I + n / 2的值全部删去就可以,如果Archer中间捣乱删除了warrior本来应该删除的,那么warrior就删除掉arr[I]或者arr[I + n / 2],这样结果就比P小了。
ans也肯定是大于等于P的,我们将n-2次选择看成(n - 2) / 2次回合,每一回合warrior先选,对于Archer来讲,无论warrior先选什么,假设其选J,archer只要选对应的J + n / 2或者 J - n / 2即可,最后剩余的一对一定大于等于P。
综上,ans=P = min{arr[i + n / 2] - arr[i]}
代码很简单了,就不贴了

D. Max and Bike
题意大概就是自行车轮子上有标记,车位置任意(起点之前),从标记与起点重合开始计时,到标记与终点重合结束,求这段时间的最小值。
假设从开始到结束标记转了T圈,T为浮点数,T的整数部分时间肯定是确定的,2*PI*R/V*int(T)。现在考虑小数部分t,t可以转化为a, a代表转得角度,在这段时间内走得距离D=(f-s-int(T)*2*PI*R)是一定的,如何使t尽量小?这样就只能走圆的上方最快,因为速度是一定的,额外的速度来自于标记跟随圆运动时的水平速度,圆上方时这个分量是最大的,所以画图可以知道sin(a/2)*2+t*2*PI*R等于D,二分确定t的最小值即可

#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))
#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))
#define LL long long
#define ALL(v) v.begin(),v.end()
#define ZERO(v) memset(v, 0, sizeof v)
#define NEG(v)  memset(v, -1, sizeof v)
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MOD 1000000007
#define PI 3.141592653589793
inline long double min(long double a , long double b) {if(a < b)return a; return b;}
inline long double max(long double a , long double b) {if(a < b)return b; return a;}

int n;
int r;
int v;
double s,f;
int fff;
int sss;
double ff(double val)
{
    return 2 * sin(val) * r + 2 * val * r;
}
double solve()
{

    s = sss;
    f = fff;
    double circle = 2 * PI * r;
    double roundTime = circle / v;
    double res = 0;
    double times = (f - s) / circle;
    int timesInt = times;
    f -= timesInt * circle;
    res += roundTime * timesInt;
    double dis = f - s;
    double l = 0;
    double h = PI;
    //cout << dis << " " << res << endl;
    for(int i = 0; i < 100; i++)
    {
        double m = (l + h) / 2;
        if(ff(m) > dis)
            h = m;
        else
            l = m;
    }
    //cout << l / 2 / PI * 360 << endl;
    res += 2 * l * r / v;
    return res;

}
int main(){

    cout << setprecision(15);
    cin >> n;
    cin >> r >> v;
    FOR(i,0,n)
    {
        scanf("%d%d", &sss, &fff);
        cout << solve () << endl;
    }
    return 0;
}

E. 没做出来,做了再更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值