M Maimai DX 2077
题意
有个音游叫 Maimai DX 2077。 这个音游有四种音符,每种音符有五个判定。 不同音符的不同判定会获得不同基础分数。 绝赞的判定单独计算分数。 给定一次游玩每种音符每种判定的数量,问达成度。
代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
#define pii pair<int,int>
using namespace std;
int t[5],h[5],s[5],b[5];
double st=0,sh=0,ss=0,sb=0,e=0;
signed main()
{
IOS;
int i,j;
cin>>t[0]>>t[1]>>t[2]>>t[3]>>t[4];
cin>>h[0]>>h[1]>>h[2]>>h[3]>>h[4];
cin>>s[0]>>s[1]>>s[2]>>s[3]>>s[4];
cin>>b[0]>>b[1]>>b[2]>>b[3]>>b[4];
st=((t[0]+t[1])*1.0+t[2]*0.8+t[3]*0.5);
sh=((h[0]+h[1])*2.0+h[2]*1.6+h[3]*1.0);
ss=((s[0]+s[1])*3.0+s[2]*2.4+s[3]*1.5);
sb=((b[0]+b[1])*5.0+b[2]*2.5+b[3]*2.0);
e=b[0]*1.0+b[1]*0.5+b[2]*0.4+b[3]*0.3;
double a0=st+sh+ss+sb;
double b0=e;
double a=0,bb=0;
a=(t[0]+t[1]+t[2]+t[3]+t[4])*1.0
+(h[0]+h[1]+h[2]+h[3]+h[4])*2.0
+(s[0]+s[1]+s[2]+s[3]+s[4])*3.0
+(b[0]+b[1]+b[2]+b[3]+b[4])*5.0;
bb=(b[0]+b[1]+b[2]+b[3]+b[4])*1.0;
cout<<fixed<<setprecision(9)<<100.0*a0/a+b0/bb<<endl;
return 0;
}
E Everyone is bot
题意
有 n 个人打算在群里复读。 一次复读的过程如下: 每一轮,n 个人按照编号从小到大依次执行以下操作。 如果这个人在前几轮已经进行过复读,他不会再次复读。也就是说,每个人最多只会复读一次。 否则他可以选择是否进行复读。 如果某一轮没有人进行复读,那么复读的过程结束。 对于第 i 个人,如果他是所有人中第 j 个进行复读的,他会获得 ai,j 瓶冰红茶。但是如果他是所有进行了复读的人当中倒数第 p 个进行复读的人,那么他不会获得任何冰红茶,并且需要交给咩噗特雷格博154 瓶冰红茶 (即获得 −154 杯冰红茶)。 每个人都想最大化自己获得的冰红茶数量,求所有人一共会拿到多少冰红茶。
思路
总复读人数是nmodp。因为每个人都想获得冰红茶,所以只要他不处于倒数第p个,他就会参与复读。从后往前思考,如果当前已经有n−p个人复读了,那么不会有人愿意成为倒数第p个,所以后面不会有任何人复读。如果当前已有n-2p个人复读了,那么不会有人愿意成为倒数第2p个,因为在他之后必然有人接着复读,当达到n-p时必定没有人愿意复读,此时他便会上交154瓶冰红茶。由此可见,如果当前复读人数是n−kp那么后面不会有人复读。因而只会有前nmodp个人复读。
代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
#define pii pair<int,int>
using namespace std;
int a[1005][1005];
signed main()
{
IOS;
int n,p;
cin>>n>>p;
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
for(i=1;i<=n%p;i++)
{
cout<<a[i][i]<<" ";
}
for(;i<=n;i++)
{
cout<<"0 ";
}
return 0;
}
H Here is an Easy Problem of Zero-chan
题意
有一棵n个节点且以1为根的有根树。第i个点的点权为i。多次查询编号为 x 的点, ∏lca(i, x) 的末尾有多少个零。
思路
问题可以转变成为求它能分解出2和5的最小值作为因子。可以将点分为两类,对于处于x的子树内的点,与x的lca均为x;而不处于x的子树内的点,那么他们的lca均为x的祖先。所以对于查询x而言,可以枚举x到根节点的所有节点,对于每个点计算有多少个点与x不在同一个儿子子树内。对于点x,他的父亲节点fax对于祖先路径上的权值计算与x相同,所以可以采用树形dp来减少重复的计算。 则可以得到转移式dpx=dpfax+sizex×(cntx2|5−cntfax2|5),其中sizex代表 x 的子树大小,cntx2|5代表节点x能分解出多少个2或5。
代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
#define pii pair<int,int>
using namespace std;
int n,q;
int u,v;
int x;
int dp5[100005],dp2[100005];//答案中2和5的个数
int num2[100005],num5[100005];
vector<int>g[100005];
int er[100005];//子树的结点个数
void dfs(int u,int fa)//求子树大小,即er[]
{
er[u]=1;
for(auto i:g[u])
{
if(i==fa)
continue;
dfs(i,u);
er[u]+=er[i];
}
}
void dfs1(int u,int fa)
{
dp2[u]=dp2[fa]+er[u]*(num2[u]-num2[fa]);
dp5[u]=dp5[fa]+er[u]*(num5[u]-num5[fa]);
for(auto i:g[u])
{
if(i==fa)
continue;
dfs1(i,u);
}
}
signed main()
{
IOS;
cin>>n>>q;
int i,j,k;
for(i=1;i<=n;i++)
{
k=i;
while(k%2==0)
{
num2[i]++;
k/=2;
}
while(k%5==0)
{
num5[i]++;
k/=5;
}
}
for(i=1;i<n;i++)
{
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
dfs1(1,0);
while(q--)
{
cin>>x;
cout<<min(dp2[x],dp5[x])<<endl;
}
return 0;
}