alice and cake
思路
- 自顶向下模拟
- 当前蛋糕最大值大于a最大值,那么需要切割该最大值。(如果不切最终结果一定不是a)
- 当前蛋糕最大值等于a最大值那么两者一定可以匹配,然后考虑子问题即可。
- 否则报错。
int main()
{
int t;
cin>>t;
for(int i = 0;i<t;i++)
{
int n;
cin>>n;
priority_queue<ll,vector<ll>> q;
priority_queue<ll,vector<ll>> p;
ll sum = 0;
for(int k =0;k<n;k++)
{
ll a;cin>>a;
q.push(a);
sum+=a;
}
p.push(sum);
bool flag = true;
while(!q.empty())
{
ll a = q.top();
q.pop();
ll b = p.top();
p.pop();
if(a>b)
{
flag = false;break;
}
else if(a<b) //继续切成两块
{
q.push(a);
p.push(b/2); //切成两块
p.push(b-b/2);
}
//不能再切了,当前最大值匹配
}
if(flag&&q.empty()&&p.empty()) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
system("pause");
}
D题Potion Brewing Class(前置知识缺乏)
思路
- 每个点的最简分数形式。分母的最小公倍数就是答案
- 如何求最小公倍数?考察每个分母的素数因子,对每个出现的素数因子的次数在所有分母中求最大值。最后的答案就是最小公倍数
- 如何求解最大值?使用cnt维护即可。并预处理每个数的所有质因数
预处理所有数的质因数:
for(int i = 2;i<=200000;i++)
{
int t_1 = i;
//对于t_1分解质因数
for(int j = 2;j<=sqrt(i);j++)
{
while(t_1%j==0)
{
m[i][j]++; //质因数加1
t_1/=j;
}
}
//不含有任何因子,本身是因数
if(t_1>1)
m[i][i]++;
}
维护cnt。m[i][j]记录数i中素数j因子出现的次数。注意maximal只有在加的时候更新。
void dfs(int from,int st,map<int,int>m[200005],ll cnt[200005],vector<pair<int,pair<int,int>>> adjmap[],int n)
{
for(pair<int,pair<int,int>> a:adjmap[st])
{
if(a.first!=from)
{
int v = a.first;
//加上y的所有因子
int y = a.second.second;
int x = a.second.first;
for(pair<int,int> b:m[x]) cnt[b.first]-=b.second;
for(pair<int,int> b:m[y])
{
cnt[b.first]+=b.second;
maximal[b.first] = max(maximal[b.first],cnt[b.first]);
}
//更新对应因子的最大值
dfs(st,v,m,cnt,adjmap,n);
for(pair<int,int> b:m[x]) cnt[b.first]+=b.second;
for(pair<int,int> b:m[y])
{
cnt[b.first]-=b.second;
}
}
}
}
最后只需使用cnt求出该最小公倍数。然后再dfs一次求出所有和。(使用带模计算模板类)。等补完一些基础知识再来。