A. Golden Spirit
签到题,首先把所有老人带到对岸,然后在对休息讨论一下即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int main()
{
IO;
int T=1;
cin>>T;
while(T--)
{
ll n,x,t;
cin>>n>>x>>t;
ll p=2*n*t;
if(p-2*t>=x) cout<<2*p<<'\n';
else
{
ll w=x-p+2*t;
if(w>=t)
{
p+=t;
cout<<2*n*t+p+max(0ll,x-2*n*t)<<'\n';
}
else
cout<<2*p+w<<'\n';
}
}
return 0;
}
C. Rencontre
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
//#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int n,m;
int h[N],e[2*N],ne[2*N],idx;
ll w[2*N];
int sz[N];
int can[N][4];
int cnt[4];
void add(int a,int b,ll c)
{
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
ll res1,res2,res3;
void dfs(int u,int fa)
{
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(j==fa) continue;
dfs(j,u);
for(int k=1;k<=3;k++) can[u][k]+=can[j][k];
res1+=w[i]*can[j][1]*(cnt[2]-can[j][2])+w[i]*can[j][2]*(cnt[1]-can[j][1]);
res2+=w[i]*can[j][2]*(cnt[3]-can[j][3])+w[i]*can[j][3]*(cnt[2]-can[j][2]);
res3+=w[i]*can[j][3]*(cnt[1]-can[j][1])+w[i]*can[j][1]*(cnt[3]-can[j][3]);
}
}
int main()
{
IO;
int T=1;
//cin>>T;
while(T--)
{
memset(h,-1,sizeof h);
cin>>n;
for(int i=1;i<n;i++)
{
int a,b;
ll c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
for(int i=1;i<=3;i++)
{
cin>>cnt[i];
for(int j=1;j<=cnt[i];j++)
{
int x;
cin>>x;
can[x][i]=1;
}
}
dfs(1,-1);
double d1=(double)res1/((double)cnt[1]*cnt[2]);
double d2=(double)res2/((double)cnt[3]*cnt[2]);
double d3=(double)res3/((double)cnt[1]*cnt[3]);
double ans=(d1+d2+d3)/2;
printf("%.9lf\n",ans);
}
return 0;
}
自己非常害怕树的问题,尤其是树形dp之类的
总结:像这种考虑贡献的可以尝试逐点考虑或者逐边考虑(本题)
D. ABC Conjecture
c
=
p
1
α
1
p
2
α
2
…
p
k
α
k
c=p_1^{\alpha_1}p_2^{\alpha_2}\dots p_k^{\alpha_k}
c=p1α1p2α2…pkαk
只要存在
α
i
>
1
\alpha_i>1
αi>1就能够满足题意,如下尝试构造一组
a
b
ab
ab,不妨设
α
i
>
1
\alpha_i>1
αi>1
a
=
p
1
α
1
…
(
p
i
α
i
−
1
)
…
p
1
α
1
a=p_1^{\alpha_1}\dots (p_i^{\alpha_i-1})\dots p_1^{\alpha_1}
a=p1α1…(piαi−1)…p1α1
b
=
p
1
α
1
…
[
(
p
i
−
1
)
×
p
i
α
i
−
1
]
…
p
1
α
1
b=p_1^{\alpha_1}\dots [(p_i-1)×p_i^{\alpha_i-1}]\dots p_1^{\alpha_1}
b=p1α1…[(pi−1)×piαi−1]…p1α1
明显上述
a
+
b
=
c
a+b=c
a+b=c,且由于
p
i
−
1
<
p
i
p_i-1<p_i
pi−1<pi,脑补一下
r
a
d
(
a
b
c
)
<
c
rad(abc)<c
rad(abc)<c一定成立
由于c范围很大,如果你只会线性筛只需要先线性筛质数,然后试除法分解质因数,但是可能分解不彻底,对于分解之后剩下的部分只需要特判一下(由于 ( 1 0 7 ) 3 > 1 0 18 (10^7)^3>10^{18} (107)3>1018),如果存在大于 1 0 7 10^7 107的质因数,该质因数的次幂最大是2。由此可特判
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=10000010;
int cnt,prime[N];
bool st[N];
void init(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i]) prime[++cnt]=i;
for(int j=1;prime[j]<=n/i;j++)
{
st[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
int main()
{
IO;
int T=1;
cin>>T;
init(10000000);
while(T--)
{
ll c;
cin>>c;
bool ok=0;
for(int i=1;i<=cnt;i++)
{
ll p=prime[i];
int s=0;
if(c%p==0)
{
while(c%p==0)
c/=p,s++;
}
if(s>=2) ok=1;
}
ll x=sqrt(c);
if(c>1&&1ll*x*x==c) ok=1;
if(ok) cout<<"yes\n";
else cout<<"no\n";
}
return 0;
}
如果没想到上述特判方法那么需要更快速的方法分解质因数,Pollard’s rho模板题?我想可能出题人本意不是这个,会的越多就能越暴力解决问题,降低思维难度!!!
总结:做题还是需要多想想,而且要相信对于自己现在的掌握的算法已经足够解决一些题目。
G. Caesar Cipher
线段树+hash
看到这个题想到hash了,不过由于hash需要取模而且题目中也需要取模自己就非常乱,根本不明白什么时候取哪个模😵
看到正解后发现非常巧妙,由于每次只进行+1,而且对于65536取模,最终可以知道q次询问后溢出数的总个数不会很多,由此每次进行区间+1后我们check一下是否有溢出的数,如果有直接单点修改即可,只需要多维护一个区间最大值mx。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=500010,P=131;
const int mod1=1e9+7;
const int mod2=65536;
struct node
{
int l,r;
ll lazy;
ll hs,mx;
}tree[N<<2];
ll p[N],one[N];
int n,q;
void pushup(int u)
{
int len=tree[u<<1|1].r-tree[u<<1|1].l+1;
tree[u].hs=(tree[u<<1].hs*p[len]%mod1+tree[u<<1|1].hs)%mod1;
tree[u].mx=max(tree[u<<1].mx,tree[u<<1|1].mx);
}
void build(int u,int l,int r)
{
tree[u]={l,r,0};
if(l==r)
{
cin>>tree[u].hs;
tree[u].mx=tree[u].hs;
return;
}
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void pushdown(int u)
{
if(tree[u].lazy==0) return;
int lenl=tree[u<<1].r-tree[u<<1].l+1;
int lenr=tree[u<<1|1].r-tree[u<<1|1].l+1;
tree[u<<1].hs=(tree[u<<1].hs+tree[u].lazy*one[lenl]%mod1)%mod1;
tree[u<<1|1].hs=(tree[u<<1|1].hs+tree[u].lazy*one[lenr]%mod1)%mod1;
tree[u<<1].mx+=tree[u].lazy;
tree[u<<1|1].mx+=tree[u].lazy;
tree[u<<1].lazy+=tree[u].lazy;
tree[u<<1|1].lazy+=tree[u].lazy;
tree[u].lazy=0;
}
void add(int u,int l,int r)
{
if(l<=tree[u].l&&tree[u].r<=r)
{
tree[u].lazy++;
tree[u].mx++;
int len=tree[u].r-tree[u].l+1;
tree[u].hs=(tree[u].hs+one[len])%mod1;
return;
}
pushdown(u);
int mid=tree[u].l+tree[u].r>>1;
if(l<=mid) add(u<<1,l,r);
if(r>mid) add(u<<1|1,l,r);
pushup(u);
}
ll query(int u,int l,int r)
{
if(l<=tree[u].l&&tree[u].r<=r) return tree[u].hs;
pushdown(u);
int mid=tree[u].r+tree[u].l>>1;
ll v=0;
if(r<=mid) v=query(u<<1,l,r);
else if(l>mid) v=query(u<<1|1,l,r);
else
v=(query(u<<1,l,mid)*p[r-mid]%mod1+query(u<<1|1,mid+1,r))%mod1;
return v;
}
void check(int u)
{
if(tree[u].mx<mod2) return;
if(tree[u].l==tree[u].r)
{
tree[u].mx-=mod2;
tree[u].hs-=mod2;
return;
}
pushdown(u);
if(tree[u<<1].mx>=mod2) check(u<<1);
if(tree[u<<1|1].mx>=mod2) check(u<<1|1);
pushup(u);
}
int main()
{
IO;
int T=1;
//cin>>T;
while(T--)
{
cin>>n>>q;
p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*P%mod1,one[i]=(one[i-1]*P%mod1+1)%mod1;
build(1,1,n);
while(q--)
{
int op,l,r;
cin>>op>>l>>r;
if(op==1)
{
add(1,l,r);
check(1);
}
else
{
int len;
cin>>len;
if(query(1,l,l+len-1)==query(1,r,r+len-1)) cout<<"yes\n";
else cout<<"no\n";
}
}
}
return 0;
}
H. Message Bomb
大佬题解
c
n
t
i
cnt_i
cnti当前群消息个数,
a
n
s
i
ans_i
ansi第
i
i
i个人收到消息个数,用一个set记录当前某人所在的群聊。
差分的思想:一个人加入群聊时减去该群聊之前的消息数,退出群聊时加上该群聊当前的消息数,最后加上未退出的群聊消息数
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
//#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int n,m,s;
int cnt[N];
int ans[N];
set<int> g[N];
int main()
{
IO;
int T=1;
//cin>>T;
while(T--)
{
cin>>n>>m>>s;
while(s--)
{
int op,x,y;
cin>>op>>x>>y;
if(op==1)
{
g[x].insert(y);
ans[x]-=cnt[y];
}
else if(op==2)
{
g[x].erase(y);
ans[x]+=cnt[y];
}
else
{
cnt[y]++;
ans[x]--;
}
}
for(int i=1;i<=m;i++)
{
for(auto t:g[i])
ans[i]+=cnt[t];
cout<<ans[i]<<'\n';
}
}
return 0;
}
L. Clock Master
筛素数+分组背包
#include<cmath>
中的log()
用不得!!!
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=30010;
double f[N];
int prime[N],cnt;
bool st[N];
double lg[N];
void init(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i]) prime[++cnt]=i;
for(int j=1;prime[j]<=n/i;j++)
{
st[prime[j]*i]=1;
if(i%prime[j]==0) break;
}
}
}
int main()
{
IO;
int T=1;
cin>>T;
init(30000);
for(int i=1;i<=30000;i++) lg[i]=log(i);
for(int i=1;i<=cnt;i++)
{
for(int j=30000;j>=0;j--)
{
ll v=1;
for(int k=1;;k++)
{
v=v*prime[i];
if(v>j) break;
f[j]=max(f[j],f[j-v]+k*lg[prime[i]]);
}
}
}
while(T--)
{
int b;
cin>>b;
printf("%.7lf\n",f[b]);
}
return 0;
}