NOIP2018模擬賽 10.20
阿新 • • 發佈:2018-12-16
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; }