NOIP2018模拟赛 10.20

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; 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值