T1 死宅与陷阱
用DFS预处理出每个节点被走道的概率(注意每个节点可能会被多条路到达)
然后sort排序,贪心把炸弹放到除起点外概率最高的的点。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
int n,m,p,s,t,head[N],tot=0,a[N],cnt=0,v[N];
double ans=0,val[N];
struct edge{
int ver,to;
double v;
}e[N];
int read(){
int sum=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
void print(int x){
if(x<0){putchar('-');x=-x;}
if(x>9)print(x/10);
putchar(x%10+'0');
}
void add(int x,int y,double z){
e[++tot].ver=y;
e[tot].v=z;
e[tot].to=head[x];
head[x]=tot;
}
void dfs(int x,double now){
for(int i=head[x];i;i=e[i].to)
{
int y=e[i].ver;
val[y]+=now*e[i].v;
ans+=a[y]*now*e[i].v;
dfs(y,e[i].v*now);
}
}
bool comp(double x,double y){
return x>y;
}
int main(){
// freopen("trap.in","r",stdin);
// freopen("trap.out","w",stdout);
n=read();m=read();p=read();s=read();t=read();
for(int i=1;i<=n;i++)
a[i]=read();
int x,y;double z;
for(int i=1;i<=m;i++)
{
x=read();y=read();
scanf("%lf",&z);
add(x,y,z);
}
ans+=a[s]*1.0;
dfs(s,1);
sort(val+1,val+n+1,comp);
for(int i=1;i<=t;i++)
{
ans+=p*val[i];
}
printf("%.3lf",ans);
return 0;
}
T2 抗议
f[i]:前j个奶牛分组的方案数
sum[i]:前i个奶牛的前缀和
朴素DP:当sun[j]<sum[i] f[i]+=f[j] (j<i)
若能转移,j的前缀和要小于等于i的前缀和(j+1~i区间和为非负)
直接做会超时,只有80pts
所以可以离散化后用树状树组维护前缀和
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005,mod=1000000009;
int n,cnt;
ll ans,t[N];
struct st{
int id,num;
ll sum;
}a[N];
ll read(){
ll sum=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
void print(ll x){
if(x<0){putchar('-');x=-x;}
if(x>9)print(x/10);
putchar(x%10+'0');
}
bool comp1(st a,st b){
return a.sum<b.sum;
}
bool comp2(st a,st b){
return a.id<b.id;
}
int lowbit(int x)
{
return x&(-x);
}
int ask(int x)
{
int ans=0;
while(x)
{
ans=(ans+t[x])%mod;
x-=lowbit(x);
}
return ans;
}
void add(int x,int val)
{
while(x<=cnt)
{
t[x]=(t[x]+val)%mod;
x+=lowbit(x);
}
}
int main(){
// freopen("protest.in","r",stdin);
// freopen("protest.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
{
a[i].sum=read();
a[i].sum+=a[i-1].sum;
a[i].id=i;
}
sort(a,a+n+1,comp1);
cnt=1;
a[0].num=1;
for(int i=1;i<=n;i++)
if(a[i].sum==a[i-1].sum)a[i].num=cnt;
else a[i].num=++cnt;
sort(a,a+n+1,comp2);
add(a[0].num,1);
for(int i=1;i<=n;i++)
{
ans=ask(a[i].num)%mod;
add(a[i].num,ans);
}
print(ans);
return 0;
}
T3 蒲公英的约定
本来以为是BSGS,结果只有40分orz
但观察可得,答案是可以通过最后倒推得到的。
最后要使异或值为0,那lastans=c
因为lastans=b ^ c 所以b=lastans^ c 所以我们倒着异或,就可以得到每个x,再快速幂,得到每个b
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
int a[N],c[N],ans[N],tot=0,b,x,p;
int read(){
int sum=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
int pow(int a,int b)
{
int sum=1;
while(b>0)
{
if(b&1)sum=(ll)sum*a%p;
a=(ll)a*a%p;
b>>=1;
}
return sum;
}
int main(){
// freopen("dandelion.in","r",stdin);
// freopen("dandelion.out","w",stdout);
p=read();
tot=0;
while(cin>>a[++tot])cin>>c[tot];
tot--;
x=c[tot];
for(int i=tot-1;i>=1;i--){
ans[i]=x;
b=pow(a[i],x);
x=c[i]^b;
}
for(int i=1;i<tot;i++)
printf("%d\n",ans[i]);
return 0;
}