T1 死宅与陷阱
分析
这道题比较简单,95分做法是用DFS预处理出,每个节点被走道的概率,在sort一波,贪心的思想把炸弹放到除起点外概率最高的的点。
100分做法是把DFS改成拓扑排序。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
using namespace std;
typedef long long ll;
typedef double db;
const int MAXN = 1e5+5;
int n, m, s, t;
int cnt, Head[MAXN], To[MAXN], Next[MAXN], Dgree[MAXN];
db q, Edge[MAXN], Exp[MAXN], Val[MAXN];
bool comp(db a, db b){ return a > b; }
void addEdge(int x, int y, db z)
{
To[++cnt] = y; Edge[cnt] = z;
Next[cnt] = Head[x], Head[x] = cnt;
}
void Toposort()
{
Exp[s] = 1.0;
queue<int> q;
int h = 1, t = 0;
for(int i = 1; i <= n; i++)
if(!Dgree[i]) q.push(i);//que[++t] = i;
while(q.size())
{
int x = q.front(); q.pop();
for(int i = Head[x]; i; i = Next[i])
{
int y = To[i];
db z = Edge[i];
Exp[y] += Exp[x] * z;
Dgree[y]--;
if(!Dgree[y]) q.push(y);
}
}
}
int main()
{
scanf("%d%d%lf%d%d", &n, &m, &q, &s, &t);
int u, v;
db x;
for(int i = 1; i <= n; i++)
scanf("%lf", &Val[i]);
for(int i = 1; i <= m; i++)
{
scanf("%d%d%lf", &u, &v, &x);
Dgree[v]++;
addEdge(u, v, x);
}
Toposort();
db Ans = 0;
for(int i = 1; i <= n; i++)
Ans += Exp[i] * Val[i];
int tot = 0;
// doe(int i = 1; i <= n; i++) if(i != s)
sort(Exp+1, Exp+n+1, comp);
for(int i = 1; i <= t; i++)
Ans += Exp[i+1] * q;
printf("%.3lf", Ans);
return 0;
}
T2 抗议
分析
这道题我们设f[i]表示到第i头奶牛科供选择的方案数,那么这道题我们先sort前缀和,对一个点i,如果存在一个j,j<i&&sum[i]>sum[j]那么i为正数,i这个点的方案数等于前面点j的方案数的总和(sum[i]>sum[j])
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=1e5+5;
const int MOD=1e9+9;
typedef long long ll;
struct Node
{
ll Val;
int Idx;
int Spe;
}Cow[MAXN];
bool cmp1(Node a,Node b) { return a.Val < b.Val; }
bool cmp2(Node a,Node b){ return a.Idx < b.Idx; }
int c[MAXN];
int lowbit(int i) { return i&(-i); }
void update(int x,int add)
{
while(x < MAXN)
{
c[x] = (c[x]+add) % MOD;
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while(x)
{
ans=(ans+c[x])%MOD;
x-=lowbit(x);
}
return ans;
}
int main()
{
// freopen("protest.in","r",stdin);
// freopen("protest.out","w",stdout);
int n;
scanf("%d",&n);
Cow[0].Idx=0,Cow[0].Val=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&Cow[i].Val);
Cow[i].Val=Cow[i].Val+Cow[i-1].Val;
Cow[i].Idx=i;
}
sort(Cow,Cow+1+n,cmp1);
Cow[0].Spe=1;
int cnt=1;
for(int i=1;i<=n;i++)
{
if(Cow[i].Val==Cow[i-1].Val)
Cow[i].Spe=cnt;
else
Cow[i].Spe=++cnt;
}
sort(Cow,Cow+1+n,cmp2);
int Ans=0;
update(Cow[0].Spe,1);
for(int i=1;i<=n;i++)
{
Ans=query(Cow[i]. Spe);
update(Cow[i].Spe, Ans);
}
printf("%d\n",Ans);
return 0;
}
T3 蒲公英的约定
分析
这道题基本操作是BSGS, 但是我们这道题可以发现,答案是可以通过最后倒推得到的。
推导答案:LastAns^c = 0, x = c, ax(%p)同余b求得b,最后倒序输出
using namespace std;
typedef long long ll;
ll power(ll a,ll b,ll p)
{
ll ans = 1;
while(b)
{
if(b&1) ans = ans * a % p;
b >>= 1;
a *= a;
a %= p;
}
return ans % p;
}
ll p, a[100001], c[100001], ans[100001];
ll cnt = 1;
ll lastans;
int main()
{
cin>>p;
while(scanf("%d%d", &a[++cnt], &c[cnt]) == 2) {}
cnt -= 2;
ans[cnt-1] = c[cnt];
for(int i = cnt-2; i >= 1; i--)
{
ll temp = power(a[i+2], ans[i+1], p);
ans[i] = c[i+1] ^ temp;
}
for(int i = 1; i <= cnt-1; i++) printf("%d\n", ans[i]);
return 0;
}