这次太狗血了,进行到一半结果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[];
int a[];
int powTen(int kk)
{
int res= ;
while(kk)
{
res *= ;
kk--;
}
return res;
}
LL solve(int index)
{
int aa = a[index];
int bb = b[index];
int end = powTen(k) - ;
end = end/aa * aa;
int tot = end / aa + ;
int start = bb * powTen(k - );
end = (bb + ) * powTen(k - ) - ;
end = end / aa * aa;
if(start % aa != )
start = (start / aa + ) * aa;
if(end >= start)
{
tot -= (end - start) / aa;
tot--;
}
return tot;
}
int main(){
cin >> n;
cin >> k;
FOR(i,,n/k)
scanf("%d", &a[i]);
FOR(i,,n/k)
scanf("%d", &b[i]);
LL res = ;
FOR(i,,n/k)
{
res *= solve(i);
res %= MOD;
}
cout << res << endl;
return ;
}
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 * sin(val) * r + * val * r;
}
double solve()
{
s = sss;
f = fff;
double circle = * PI * r;
double roundTime = circle / v;
double res = ;
double times = (f - s) / circle;
int timesInt = times;
f -= timesInt * circle;
res += roundTime * timesInt;
double dis = f - s;
double l = ;
double h = PI;
//cout << dis << " " << res << endl;
for(int i = ; i < ; i++)
{
double m = (l + h) / ;
if(ff(m) > dis)
h = m;
else
l = m;
}
//cout << l / 2 / PI * 360 << endl;
res += * l * r / v;
return res;
}
int main(){
cout << setprecision();
cin >> n;
cin >> r >> v;
FOR(i,,n)
{
scanf("%d%d", &sss, &fff);
cout << solve () << endl;
}
return ;
}
E. 没做出来,做了再更新