题目:Final Exam
链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1006&cid=854
大意:有n(1e9)个问题,出题人会在每个问题分配一些分数a[i]∈[0,m], ∑ a [ i ] = m \sum a[i]=m ∑a[i]=m,m∈[1,1e9],小明同学可以在每个问题上分配一些学习时间b[i],对于问题i,当且仅当 b [ i ] > a [ i ] b[i] > a[i] b[i]>a[i]时,小明能答出第i道题,小明想要至少答出k(k∈[1,1e9])道题,求满足要求的 min ( ∑ b ) \min(\sum b) min(∑b)
分析:
代码
#include
#define F(i,a,b) for(int i=(a);i<=int(b);++i)
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = int(20);
#define endl '\n'
ll n, m, k;
int main()
{
#ifndef endl
freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
cout << "************************************Local Test*********************************" << endl;
#endif // !endl
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T(1), cas(0);
cin >> T;
while (cas, T--)
{
ll ans;
cin >> n >> m >> k;
ll mo= (n - k + 1);
ll shang = m / (n - k + 1);
ll yu = m % (n - k + 1);
if (yu==mo-1)
{
ans = (m + 1) / mo * n;
}
else
{
ans = shang * n + (yu + k);
}
ans = min(ans, (m + 1)*k);
cout << ans << endl;
}
return 0;
}
//What to Debug
/*
-1.最好把全部warning都X掉,否则:https://vjudge.net/solution/19887176
0.看看自己是否有可能需要快读,禁endl
1.数组越界,爆int,浮点精度(查看精度是否达到题目要求,看有没有浮点数比较:eps),取模操作,初始化数组,边缘数据,输出格式(cas),强制在线是否更新了las
2.通读代码,代码无逻辑错误
3.读题,找到题意理解失误或算法错误
4.放弃
*/
题目:Just Repeat
链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1010&cid=854
大意:两个人玩牌,2人分别由n,m张牌,每张牌有一个颜色,两人轮流出牌,且对于颜色c,如果如果对方出过颜色c的牌,那自己就不能再出颜色c的牌,先不能出牌的输(包括牌出完了和自己的牌的颜色都是对方出过的)
分析:对于颜色c,如果只有一个人有这种颜色的牌,那这个人的步数就加上它拥有这种颜色的牌的数量。如果两个人都有这种颜色的牌,那假如先手有 c i c_i ci张c,后手有 d i d_i di张c,那第一打出颜色c的牌的人就能产生 c i + d i c_i+d_i ci+di的贡献(包括增加自己的步数,和减少对方的步数),于是接下来贪心地选 ( c i + d i ) (c_i+d_i) (ci+di)最大的颜色就好了。顺便说一句:颜色的值很大,不能用数组;也不能用map,会卡常,我用的unordered_map
#include
#pragma GCC optimize(3)
#include
#define F(i,a,b) for(int i=(a);i<=int(b);++i)
using namespace std;
typedef unsigned long long ull;
ull k1, k2, mod;
ull rng() {
ull k3 = k1, k4 = k2;
k1 = k4;
k3 ^= k3 << 23;
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
return k2 + k4;
}
unordered_map<ull, int>ma[2];
struct node
{
int a, b, sum;
bool operator<(const node&ri)const
{
return sum < ri.sum;
}
};
vector<node>ns;
int n[2];
int lead(0);
void prin()
{
if (lead > 0)cout << "Cuber QQ" << '\n';
else cout << "Quber CC" << '\n';
ma[0].clear(); ma[1].clear();
ns.clear();
n[0] = n[1] = 0;
lead = 0;
}
#define endl '\n'
int main()
{
#ifndef endl
freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
cout << "************************************Local Test*********************************" << endl;
#endif // !endl
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T(1), cas(0);
cin >> T;
while (cas, T--)
{
int tp;
cin >> n[0];
cin >> n[1];
cin>> tp;
if (tp == 1)
{
F(id, 0, 1)F(i, 1, n[id])
{
ull v; cin >> v;
++ma[id][v];
}
}
else
{
cin >> k1 >> k2 >> mod;
F(i, 1, n[0])
{
ull v= rng() % mod;
ma[0][v]++;
}
cin >> k1 >> k2 >> mod;
F(i, 1, n[1])
{
ull v = rng() % mod;
ma[1][v]++;
}
}
for (auto p0 : ma[0])
{
if (ma[1].find(p0.first) != ma[1].end())
{
ns.push_back({ p0.second,ma[1][p0.first] });
ma[1].erase(p0.first);
}
else
lead += p0.second;
}
for (auto p1 : ma[1])lead -= p1.second;
for (auto&x : ns)x.sum = x.a + x.b;
sort(ns.begin(), ns.end());
reverse(ns.begin(), ns.end());
F(i, 0, ns.size() - 1)
{
if ((i & 1) == 0)
{
lead += ns[i].a;
}
else
lead -= ns[i].b;
}
prin();
}
return 0;
}
//What to Debug
/*
-1.最好把全部warning都X掉,否则:https://vjudge.net/solution/19887176
0.看看自己是否有可能需要快读,禁endl
1.数组越界,爆int,浮点精度(查看精度是否达到题目要求,看有没有浮点数比较:eps),取模操作,初始化数组,边缘数据,输出格式(cas),强制在线是否更新了las
2.通读代码,代码无逻辑错误
3.读题,找到题意理解失误或算法错误
4.放弃
*/
题目:Kejin Player
链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1011&cid=854
大意:有n(5e5)个级别,玩家刚开始1级,i级时,花费 a i a_i ai金币有 p i p_i pi概率升到i+1级,有 ( 1 − p i ) (1-p_i) (1−pi)概率掉到 x i x_i xi级,给q(5e5)个询问,从 l e i 级 升 到 r i i le_i级升到ri_i lei级升到rii级所需金币的期望
分析:设E[i]为从1级升到i级所需金币的期望,有个结论:从i级升到j级所需金币的期望 = E [ j ] − E [ i ] =E[j]-E[i] =E[j]−E[i],所以/ E [ i + 1 ] = E [ i ] + a i + ( 1 − p i ) ∗ ( E [ i + 1 ] − E [ x [ i ] ] ) E[i+1]=E[i]+a_i+(1-p_i)*(E[i+1]-E[x[i]]) E[i+1]=E[i]+ai+(1−pi)∗(E[i+1]−E[x[i]]),所以 E [ i + 1 ] = 1 / p i ∗ ( E [ i ] + a [ i ] − E [ x [ i ] ] ∗ ( 1 − p i ) ) E[i+1]=1/p_i*(E[i]+a[i]-E[x[i]]*(1-p_i)) E[i+1]=1/pi∗(E[i]+a[i]−E[x[i]]∗(1−pi)),然后算就可以了
代码
#include
#define F(i,a,b) for(int i=(a);i<=int(b);++i)
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = int(5e5+9);
const int mod = 1e9 + 7;
ll MODED(ll x)
{
x %= mod;
if (x < 0)x += mod;
if (x >= mod)x -= mod;
return x;
}
//3_2快速幂-逆元
ll qpow(ll a, ll b, ll p) //求a^bMODp
{
ll ret = 1; a %= p;
while (b)
{
if (b & 1)ret = ret * a % p;
a = a * a % p;
b >>= 1;
}
return ret;
}
////////////////求逆元//////////////////////
////////费马小定理
ll inv(ll a, ll p) //返回a对p的逆元
{
return qpow(a, p - 2, p);
}
int n, q;
int p[maxn], s[maxn], x[maxn], a[maxn];
int E[maxn];
#define endl '\n'
int main()
{
#ifndef endl
freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
cout << "************************************Local Test*********************************" << endl;
#endif // !endl
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T(1), cas(0);
cin >> T;
while (cas, T--)
{
cin >> n >> q;
F(i, 1, n)cin >> p[i] >> s[i] >> x[i] >> a[i];
F(i, 1, n)
{
p[i] = 1ll * p[i] * inv(s[i], mod) % mod;
}
E[1] = 0;
F(i, 1, n)
{
E[i + 1] = inv(p[i], mod);
ll tmp = MODED(E[i] + a[i]-1ll*E[x[i]]*(1-p[i])%mod);
E[i + 1] =1ll* E[i + 1] * tmp%mod;
//cout << E[i+1] << endl;
}
F(i, 1, q)
{
int le, ri; cin >> le >> ri;
cout << MODED(E[ri] - E[le]) << '\n';
}
}
return 0;
}
//What to Debug
/*
-1.最好把全部warning都X掉,否则:https://vjudge.net/solution/19887176
0.看看自己是否有可能需要快读,禁endl
1.数组越界,爆int,浮点精度(查看精度是否达到题目要求,看有没有浮点数比较:eps),取模操作,初始化数组,边缘数据,输出格式(cas),强制在线是否更新了las
2.通读代码,代码无逻辑错误
3.读题,找到题意理解失误或算法错误
4.放弃
*/
: