20190228
T1
Alice和Bob又双叒叕开始玩游戏了。
有一个包含 NNN 个正整数的序列,序列元素不大于 NNN 。紧接着,他们维护了一个可重集合 SSS ,包含序列中的前 PPP 个元素。Alice先手,二人轮流进行下面的一系列操作:
1)从集合 SSS 中拿走一个元素,加到玩家的总分上面;
2)将序列中的下一个数字(如果存在)添加到集合 SSS 中;
这意味着游戏开始时,当第一个数从集合 SSS 中取出后,将序列的第 P+1P+1P+1 项加入到集合 SSS 中,以此类推至集合 SSS 被取空为止。
假使二人都尽力使自己的总分最大,设游戏的结果为Alice的总分与Bob的总分之差,那么请你在给定序列和集合元素的情况下,输出游戏的结果。
题解
我们可以想到一个暴力,用堆维护集合中的数,每次取堆顶
可惜这样效率是 O(nklogn)O(nklogn)O(nklogn) 的,想想怎么优化使得效率变为 O(nk)O(nk)O(nk)
我们可以得到一开始的时候集合内的最大值 maxmaxmax ,然后设一个计数器记录每个数出现了多少次
然后再设刚放进来的数为 nownownow ,那如果 nownownow 为 000 的话我们可以取 maxmaxmax 并且扫计数器找出下一个 maxmaxmax
如果 nownownow 不为 000 的话取出 nownownow
然后更新 nownownow 的话只需要把要放进来的数和 maxmaxmax 作比较就好了, <max<max<max 则清为 000
最后扫一遍计数器取出就可以了
T2
九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 2n2n2n 张牌,每张牌上都写着一个数字 wiw_iwi ,一共有两种类型的牌,每种类型各 nnn 张:
攻击牌:打出后对对方造成等于牌上的数字的伤害。
强化牌:打出后,假设该强化牌上的数字为 xxx ,则其他剩下的攻击牌的数字都会乘上 xxx 。保证强化牌上的数字都大于 111 。
现在九条可怜会等概率随机从卡组中抽出 mmm 张牌,由于费用限制,九条可怜最多打出 kkk 张牌,假设九条可怜永远都会采取能造成最多伤害的策略,求她期望造成多少伤害。
假设答案为 ansansans ,你只需要输出(ans×(2n)!m!(2n−m)!) mod 998244353(ans \times \frac{(2n)!}{m!(2n-m)!} ) \bmod 998244353(ans×m!(2n−m)!(2n)!)mod998244353即可
题解
挺有趣的一道题
不难发现我们要尽量选择强化牌,因为强化牌上的数 >1>1>1 ,
比如假设 a<ba<ba<b ,那么 a+b<a×2a+b<a \times 2a+b<a×2
而且我们肯定选择更大的数
所以我们现将强化牌和攻击牌排序
设 fi,jf_{i,j}fi,j 表示打出i张强化牌,最后一张是原序列中的第 jjj 张的积的和
gi,jg_{i,j}gi,j 表示打出i张攻击牌,最后一张是原序列中的第 jjj 张的和的和
可以得到转移式子:
fi,j=wj×∑k=1j−1fi−1,kf_{i,j}=w_j \times \sum_{k=1}^{j-1} f_{i-1,k}fi,j=wj×∑k=1j−1fi−1,k
gi,j=wj×Cj−1i−1+∑k=1j−1gi−1,kg_{i,j}=w_j \times C_{j-1}^{i-1} + \sum_{k=1}^{j-1} g_{i-1,k}gi,j=wj×Cj−1i−1+∑k=1j−1gi−1,k
设 Fi,jF_{i,j}Fi,j 表示选出i张强化牌,最优地打出j张牌的贡献
Gi,jG_{i,j}Gi,j 表示选出i张攻击牌,最优地打出j张牌的贡献
Fi,j=∑k=1nfj,k×Cn−ki−jF_{i,j}=\sum_{k=1}^n f_{j,k} \times C_{n-k}^{i-j}Fi,j=∑k=1nfj,k×Cn−ki−j
Gi,j=∑k=1ngj,k×Cn−ki−jG_{i,j}=\sum_{k=1}^n g_{j,k} \times C_{n-k}^{i-j}Gi,j=∑k=1ngj,k×Cn−ki−j
最终答案为 ∑i=0m−1Fi,min(i,k−1)∗Gm−i,max(k−i,1)\sum_{i=0}^{m-1} F_{i,min(i,k-1)}*G_{m-i,max(k-i,1)}∑i=0m−1Fi,min(i,k−1)∗Gm−i,max(k−i,1)
效率 O(Tn2)O(Tn^2)O(Tn2)
T3
时光匆匆,转眼间又是一年省选季……
这是小 Q 同学第二次参加省队选拔赛。今年,小 Q 痛定思痛,不再冒险偷取试题,而是通过练习旧试题提升个人实力。可是旧试题太多了,小 Q 没日没夜地做题,却看不到前方的光明在哪里。
一天,因做题过度而疲惫入睡的小 Q 梦到自己在考场上遇到了一道好像做过的题目,却怎么也想不起曾经自己是怎么解决它的,直到醒来还心有余悸。
小 Q 眉头一皱,感觉事情不妙,于是他找到了你,希望你能教他解决这道题目。小 Q 依稀记得题目要计算如下表达式的值
(∑i=1A∑j=1B∑k=1Cd(ijk)) mod (109+7)\Big(\sum_{i = 1}^{A}\sum_{j = 1}^{B}\sum_{k = 1}^{C} d(i j k) \Big) \bmod (10^9 + 7)(∑i=1A∑j=1B∑k=1Cd(ijk))mod(109+7)
其中 d(ijk)d(i j k)d(ijk) 表示 i×j×ki\times j\times ki×j×k 的约数个数。
题解
先化式子(太难了
∑i=1A∑j=1B∑k=1C∑x∣i∑y∣j∑z∣k[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]\sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^C\sum_{x|i}\sum_{y|j}\sum_{z|k}[\gcd(x,y)=1][\gcd(x,z)=1][\gcd(y,z)=1]∑i=1A∑j=1B∑k=1C∑x∣i∑y∣j∑z∣k[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]
∑x=1A∑y=1B∑z=1C[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]⌊Ax⌋⌊By⌋⌊Cz⌋\sum_{x=1}^A\sum_{y=1}^B\sum_{z=1}^C[\gcd(x,y)=1][\gcd(x,z)=1][\gcd(y,z)=1]⌊\frac{A}{x}⌋⌊\frac{B}{y}⌋⌊\frac{C}{z}⌋∑x=1A∑y=1B∑z=1C[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]⌊xA⌋⌊yB⌋⌊zC⌋
∑x=1A∑y=1B∑z=1C∑i∣x,i∣yμ(i)∑j∣x,j∣zμ(j)∑k∣y,k∣zμ(k)⌊Ax⌋⌊By⌋⌊Cz⌋\sum_{x=1}^A\sum_{y=1}^B\sum_{z=1}^C\sum_{i|x,i|y}\mu(i)\sum_{j|x,j|z}\mu(j)\sum_{k|y,k|z}\mu(k)⌊\frac{A}{x}⌋⌊\frac{B}{y}⌋⌊\frac{C}{z}⌋∑x=1A∑y=1B∑z=1C∑i∣x,i∣yμ(i)∑j∣x,j∣zμ(j)∑k∣y,k∣zμ(k)⌊xA⌋⌊yB⌋⌊zC⌋
∑i=1A∑j=1B∑k=1Cμ(i)μ(j)μ(k)∑i∣x,j∣x⌊Ax⌋∑i∣y,k∣y⌊By⌋∑j∣z,k∣z⌊Cz⌋\sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^C\mu(i)\mu(j)\mu(k)\sum_{i|x,j|x}⌊\frac{A}{x}⌋\sum_{i|y,k|y}⌊\frac{B}{y}⌋\sum_{j|z,k|z}⌊\frac{C}{z}⌋∑i=1A∑j=1B∑k=1Cμ(i)μ(j)μ(k)∑i∣x,j∣x⌊xA⌋∑i∣y,k∣y⌊yB⌋∑j∣z,k∣z⌊zC⌋
对于下去整的东西我们可以 O(nlogn)O(nlogn)O(nlogn) 进行预处理
fA(i)=∑i∣d⌊Ad⌋f_A(i)=\sum_{i|d}⌊\frac{A}{d}⌋fA(i)=∑i∣d⌊dA⌋ ( B,CB,CB,C 同理
我们考虑如何计算答案
可以发现我们考虑枚举两个数,如果它们的 lcm≤max(a,b,c)lcm \leq max(a,b,c)lcm≤max(a,b,c) 则相互连边,则对答案有贡献的就是图中的三元环了(考虑优化
先单独计算三个数相同的情况和三个数中有两个相同的情况
然后后者再两两连边,找出图中的三元环,然后计算答案
献上代码(参考了下网上别的题解
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+5,P=1e9+7;
LL ans,fa[N],fb[N],fc[N];
int T,p[N],mu[N],tp,A,B,C,ce,sa[N];
int sb[N],sc[N],d[N],n;bool vis[N];
struct E{int u,v,w;}e[N<<4];
vector<pair<int,int> >g[N];
int main(){
mu[1]=1;for (int i=2;i<N;i++){
if (!vis[i]) p[++tp]=i,mu[i]=-1;
for (int j=1;j<=tp && p[j]*i<N;j++){
vis[p[j]*i]=1;
if (i%p[j]) mu[p[j]*i]=-mu[i];
else break;
}
}
for (scanf("%d",&T);T--;){
scanf("%d%d%d",&A,&B,&C);n=max(max(A,B),C);
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j+=i)
fa[i]+=A/j,fb[i]+=B/j,fc[i]+=C/j;
// calc fd(y)=sigma_y|x d/x
for (int i=1;i<=n;i++) if (mu[i])
ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
// calc three same
for (int i=1;i<=n;i++) for (int j=1;i*j<=n;j++)
if (mu[i*j]) for (int k=j+1;1ll*i*j*k<=n;k++)
if (mu[i*k] && __gcd(j,k)==1){
int x=i*j,y=i*k,z=x*k;d[x]++;d[y]++;e[++ce]=(E){x,y,z};
ans+=mu[x]*mu[x]*mu[y]*(fa[x]*fb[z]*fc[z]+fa[z]*fb[x]*fc[z]+fa[z]*fb[z]*fc[x]);
ans+=mu[x]*mu[y]*mu[y]*(fa[y]*fb[z]*fc[z]+fa[z]*fb[y]*fc[z]+fa[z]*fb[z]*fc[y]);
}
// calc two same and link
#define u e[i].u
#define v e[i].v
for (int i=1;i<=ce;i++){
if (d[u]>d[v] || (d[u]==d[v] && u>v))
swap(u,v);g[u].push_back(make_pair(v,e[i].w));
}
#define F first
#define S second
for (int i=1;i<=n;i++){
for (int j=g[i].size()-1;~j;j--){
int x=g[i][j].F,y=g[i][j].S;
sa[x]=fa[y];sb[x]=fb[y];sc[x]=fc[y];
}
for (int j=g[i].size()-1;~j;j--){
int x=g[i][j].F,y=g[i][j].S;
for (int k=g[x].size()-1;~k;k--){
int a=g[x][k].F,b=g[x][k].S,t=mu[i]*mu[x]*mu[a];
ans+=t*fa[y]*fb[b]*sc[a];ans+=t*fa[y]*sb[a]*fc[b];
ans+=t*sa[a]*fb[y]*fc[b];ans+=t*fa[b]*fb[y]*sc[a];
ans+=t*sa[a]*fb[b]*fc[y];ans+=t*fa[b]*sb[a]*fc[y];
}
}
#define y g[i][j].F
for (int j=g[i].size()-1;~j;j--) sa[y]=sb[y]=sc[y]=0;
}
printf("%lld\n",ans%P);ans=ce=0;
for (int i=1;i<=n;i++) d[i]=fa[i]=fb[i]=fc[i]=0,g[i].clear();
}
return 0;
}