本场链接:Codeforces Round #730 (Div. 2)
A. Exciting Bets
由性质:\((a + x,b + x) = (a + x,b - a)\)故取到最大值应该是\(a+x \mod b - a == 0\)时,就有最大值\(b-a\),步数为\(x\)解出即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
int main()
{
int T;scanf("%d",&T);
while(T--)
{
ll a,b;scanf("%lld%lld",&a,&b);
if(a > b) swap(b,a);
if(a == b) puts("0 0");
else
{
ll c = b - a,s = ((-a) % c + c) % c;
printf("%lld %lld\n",b - a,min(s,c - s));
}
}
return 0;
}
B. Customising the Track
不难想到平均分配整个数组,且次序无关.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
const int N = 2e5+7;
ll a[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
forn(i,1,n) scanf("%lld",&a[i]);
ll sum = 0;forn(i,1,n) sum += a[i];
ll c = sum % n;
printf("%lld\n",(n - c) * c);
}
return 0;
}
C. Need for Pink Slips
不难想到因为\(v \geq 0.1\)所以总共的操作步数不会太多,又由于求期望的过程与当前三个概率的具体形态关联性紧密,所以枚举所有状态是一个非常可行的方向,不难想到一种将每一步取到终止状态的概率求出再总体求期望,但是由于精度问题挂掉了(傻逼).另外一种操作小一些的办法是期望dp,把状态表示成当前状态走到\((0,0,1)\)的步数,就可以确定终态的期望和转移了.
另外由于读入的就是浮点数,需要对其整数化处理.
不知道为什么扩大1e6倍后本机数据正常交上去会挂,写4e4和四舍五入能过,我只能说浮点数题我这辈子都不会做:)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
const int N = 2e5+7,M = 4e4;
int maxd;
ll v;
double dfs(ll c,ll m,ll p)
{
double res = 1;
if(c > 0)
{
ll pro = min(c,v);
if(m == 0) res += c * 1.0 / M * dfs(c - pro,0,p + pro);
else res += c * 1.0 / M * dfs(c - pro,m + pro / 2,p + pro / 2);
}
if(m > 0)
{
ll pro = min(m,v);
if(c == 0) res += m * 1.0 / M * dfs(0,m - pro,p + pro);
else res += m * 1.0 / M * dfs(c + pro / 2,m - pro,p + pro / 2);
}
return res;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
double c,m,p,_v;scanf("%lf%lf%lf%lf",&c,&m,&p,&_v);
v = _v * M + 0.5;
printf("%.18lf\n",dfs(ll(c * M + 0.5),ll(m * M + 0.5),ll(p * M + 0.5)));
}
return 0;
}
D1. RPD and Rap Sheet (Easy Version)
D1的情形等价于二进制的异或,不难根据异或的性质想到在询问了一个值\(y\)后,原本的答案\(x\)会变成\(x \oplus y\).由于答案的取值\(\in[0,n-1]\),不妨根据值域进行枚举,如果答案为\(x-1\),那么在第\(x\)次交互时,询问的值\(q_x\)需要等于当前的答案值(加密后的).
不妨一个一个处理:若\(ans == 0\)则\(q_1 == 0\)显然,若\(ans == 1\)则在第一次交互之后,\(ans == 1\)此时的\(q_2 = 1 ^0\).继续可以推出\(q_i = (i-2) \oplus (i - 1)\).直接询问即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
int query(int x)
{
cout << x << endl;
int res;cin >> res;
return res;
}
int main()
{
Angel_Dust;
int T;cin >> T;
while(T--)
{
int n,k;cin >> n >> k;
if(query(0) == 1) continue;
forn(i,1,n) if(query(i ^ (i - 1)) == 1) break;
}
return 0;
}
D2. RPD and Rap Sheet (Hard Version)
与D1相同,首先想办法求出操作的逆操作,记作\(\ominus\),由模的性质可以拿到:\(x \oplus z == y\)推出\(z = y \ominus x\).同D1推导即可.
注意是后者\(\ominus\)前者.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
int n,k;
int query(int x,int y)
{
int z=0;
int p=1;
while(x>0 || y>0)
{
int a=x%k;
x=x/k;
int b=y%k;
y=y/k;
int c=(a-b+k)%k;
z=z+p*c;
p=p*k;
}
cout << z << endl;
int res;cin >> res;
return res;
}
int main()
{
Angel_Dust;
int T;cin >> T;
while(T--)
{
cin >> n >> k;
cout << 0 << endl;
int res;cin >> res;
if(res == 1) continue;
forn(i,2,n)
{
if(i % 2 == 0) if(query(i - 2,i - 1) == 1) break;
if(i % 2 == 1) if(query(i - 1,i - 2) == 1) break;
}
}
return 0;
}