1806做题记录 I

BZOJ5340/Luogu P4564 [CTSC2018] 假面

概率与期望、动态规划

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define clr(x) memset(x,0,sizeof(x))
 5 #define mod 998244353
 6 #define MN 203
 7 using namespace std;
 8 inline int in(){
 9     int x=0;bool f=0; char c;
10     for (;(c=getchar())<'0'||c>'9';f=c=='-');
11     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
12     return f?-x:x;
13 }
14 int f[MN][MN],g[MN],p[MN],res[MN],pos[MN],m[MN],inv[MN];
15 int n,q,k,op,ps,u,v,ans;
16 inline int qpow(int x,int k){
17     int res=1;
18     while (k){
19         if (k&1) res=(1ll*res*x)%mod;
20         x=(1ll*x*x)%mod;k>>=1;
21     }return res;
22 }
23 inline void dp(int x,int v){
24     f[x][0]=(1ll*f[x][1]*v+f[x][0])%mod;
25     for (int i=1;i<=m[x];++i)
26     f[x][i]=((1ll*f[x][i+1]*v)%mod+(1ll*f[x][i]*(mod+1-v))%mod)%mod;
27 }
28 inline void query(){
29     clr(g);clr(p);clr(res);g[0]=1;
30     for (int i=1;i<=k;++i)
31     for (int j=i;j>=0;--j) 
32     if (!j) g[j]=(1ll*g[j]*f[pos[i]][0])%mod;
33     else g[j]=((1ll*g[j]*f[pos[i]][0])%mod+(1ll*g[j-1]*(mod+1-f[pos[i]][0]))%mod)%mod;
34     for (int i=1;i<=k;++i){
35         if (f[pos[i]][0]){
36             int ivm=qpow(f[pos[i]][0],mod-2);
37             for (int j=0;j<k;++j){
38                 if (j) p[j]=(1ll*(g[j]+mod-(1ll*p[j-1]*(mod+1-f[pos[i]][0]))%mod)*ivm)%mod;
39                 else p[j]=(1ll*g[j]*ivm)%mod;
40                 res[i]=(res[i]+(1ll*inv[j+1]*p[j])%mod)%mod;
41             }
42         }else{
43             for (int j=0;j<k;++j)
44             res[i]=(res[i]+(1ll*inv[j+1]*g[j+1])%mod)%mod;
45         }
46         res[i]=(1ll*res[i]*(mod+1-f[pos[i]][0]))%mod;
47     }
48     for (int i=1;i<=k;++i) printf("%d ",res[i]);puts("");
49 }
50 int main()
51 {
52     n=in();
53     for (int i=1;i<=n;++i){
54         m[i]=in();f[i][m[i]]=1;
55         inv[i]=qpow(i,mod-2);
56     }q=in();
57     for (int i=1;i<=q;++i){
58         op=in();
59         if (!op){
60             ps=in();u=in();v=in();
61             dp(ps,(1ll*u*qpow(v,mod-2))%mod);
62         }else{
63             k=in();
64             for (int i=1;i<=k;++i) pos[i]=in();query();
65         }
66     }
67     for (int i=1;i<=n;++i){
68         ans=0;
69         for (int j=1;j<=m[i];++j) ans=(ans+(1ll*f[i][j]*j)%mod)%mod;
70         printf("%d ",ans);
71     }return 0;
72 }

BZOJ 5343/Luogu P4602 [CTSC2018]混合果汁

对于每种果汁按美味度从大到小排序,以价格为下标,以每种果汁为版本建立可持久化线段树,维护果汁的体积和及价格和。

对于每种需求,二分查找果汁对应的版本,在该版本的线段树上二分,判断是否满足对果汁体积要求的情况下满足对价格的要求。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ll long long
 5 #define mid ((l+r)>>1)
 6 #define MM 2300005
 7 #define MN 100005
 8 using namespace std;
 9 inline ll in(){
10     ll x=0;bool f=0;char c;
11     for (;(c=getchar())<'0'||c>'9';f=c=='-');
12     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
13     return f?-x:x;
14 }
15 struct st{
16     int d,p;
17     ll l;
18 }a[MN];
19 int L[MM],R[MM],rt[MN];
20 ll sum[MM],cst[MM],g,k;
21 int n,m,mx,cnt,res;
22 inline bool cmp(st x,st y){return x.d>y.d;}
23 inline void build(int &x,int l,int r){
24     if (!x) x=(++cnt);if (l==r) return;
25     build(L[x],l,mid);build(R[x],mid+1,r);
26 }
27 inline void update(int &x,int l,int r,int p,ll v){
28     L[++cnt]=L[x];R[cnt]=R[x];sum[cnt]=sum[x];cst[cnt]=cst[x];x=cnt;
29     sum[x]+=v;cst[x]+=1ll*p*v;if (l==r) return;
30     if (p<=mid) update(L[x],l,mid,p,v);
31     else update(R[x],mid+1,r,p,v);
32 }
33 inline ll query(int x,int l,int r,ll v){
34     if (l==r) return l*v;
35     if (v<=sum[L[x]]) return query(L[x],l,mid,v);
36     return cst[L[x]]+query(R[x],mid+1,r,v-sum[L[x]]);
37 }
38 int main()
39 {
40     n=in();m=in();
41     for (int i=1;i<=n;++i){
42         a[i].d=in();a[i].p=in();
43         a[i].l=in();mx=max(mx,a[i].p);
44     }sort(a+1,a+n+1,cmp);build(rt[0],1,mx);
45     for (int i=1;i<=n;++i) rt[i]=rt[i-1],update(rt[i],1,mx,a[i].p,a[i].l);
46     for (int i=1;i<=m;++i){
47         g=in();k=in();
48         int l=1,r=n,res=-1;
49         while (l<=r){
50             if (k<=sum[rt[mid]]&&query(rt[mid],1,mx,k)<=g) res=mid,r=mid-1;
51             else l=mid+1;
52         }printf("%d
",(res<0?res:a[res].d));
53     }return 0;
54 }

BZOJ 1076/Luogu P2473 [SCOI2008]奖励关

期望dp.令f[i][s]表示f在前i-1轮已处理状态为s,后n-i+1轮到达此状态的期望。

枚举下一轮选择的宝物j,若j可选,则分为选择或不选择,选取较大值,否则则只能不选择。

转移方程见程序。答案即为f[1][0]的值。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MK 103
 5 #define MN 20
 6 #define MM (1<<15)
 7 using namespace std;
 8 inline int in(){
 9     int x=0;bool f=0; char c;
10     for (;(c=getchar())<'0'||c>'9';f=c=='-');
11     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
12     return f?-x:x;
13 }
14 double f[MK][MM];
15 int p[MN],v[MN],k,n,x;
16 int main()
17 {
18     k=in();n=in();
19     for (int i=0;i<n;++i){
20         v[i]=in();x=in()-1;
21         while (x>=0) p[i]+=(1<<x),x=in()-1;
22     }
23     for (int i=k;i;--i)
24     for (int s=0;s<(1<<n);++s){
25         for (int j=0;j<n;++j)
26         if ((p[j]&s)==p[j]) 
27         f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j)]+v[j]);
28         else f[i][s]+=f[i+1][s];f[i][s]/=n;
29     }printf("%.6lf",f[1][0]);return 0;
30 }

BZOJ 3668/LuoguP2114 [NOI2014]起床困难综合症

分别求出每一位是0/1的情况经过所有运算后的结果,这可以用二进制位全0/全1的数分别模拟。

在取值范围内从高位向低位贪心选取,若两种操作结果相同,则选取二进制位较小的数(即0)。否则选取使该位结果为1的数。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 inline int in(){
 6     int x=0;bool f=0; char c;
 7     for (;(c=getchar())<'0'||c>'9';f=c=='-');
 8     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
 9     return f?-x:x;
10 }
11 int n,m,x,mx,bt,b0,b1,res;
12 char ch;
13 int main()
14 {
15     n=in();m=in();b0=0;b1=-1;
16     for (int i=1;i<=n;++i){
17         ch=getchar();while (ch!='A'&&ch!='O'&&ch!='X') ch=getchar();
18         x=in();mx=max(mx,x);
19         if (ch=='A') b0&=x,b1&=x;
20         else if (ch=='O') b0|=x,b1|=x;
21         else b0^=x,b1^=x;
22     }
23     for (;mx;mx>>=1,++bt);
24     for (int i=bt-1;i>=0;--i){
25         if ((b0>>i)&1) res+=(1<<i);
26         else if ((b1&(1<<i))<=m&&((b1>>i)&1)) res+=(1<<i),m-=(1<<i);
27     }printf("%d",res);return 0;
28 }

 BZOJ1086/Luogu P2325 [SCOI2005]王室联邦

http://hzwer.com/5160.html

https://www.cnblogs.com/FallDream/p/bzoj1086.html

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MN 1005
 5 using namespace std;
 6 inline int in(){
 7     int x=0;bool f=0; char c;
 8     for (;(c=getchar())<'0'||c>'9';f=c=='-');
 9     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
10     return f?-x:x;
11 }
12 struct edge{
13     int to,nxt;
14 }e[MN<<1];
15 int h[MN],bt[MN],res[MN],cpt[MN],st[MN];
16 int n,b,x,y,ct,cnt,top=0;
17 bool vis[MN];
18 inline void ins(int x,int y){
19     e[++cnt].to=y;e[cnt].nxt=h[x];h[x]=cnt;
20 }
21 inline void dfs(int u){
22     for (int i=h[u];i;i=e[i].nxt){
23         int v=e[i].to;
24         if (vis[v]) continue;
25         vis[v]=1;bt[v]=top;dfs(v);
26         if (top-bt[u]>=b){
27             cpt[++ct]=u;
28             while (top>bt[u]) res[st[top]]=ct,--top;    
29         }
30     }st[++top]=u;
31 }
32 int main()
33 {
34     n=in();b=in();if (n<b) {printf("0");return 0;}
35     for (int i=1;i<n;++i) {
36         x=in();y=in();ins(x,y);ins(y,x);
37     }bt[1]=0;dfs(1);
38     while (top) res[st[top]]=ct,--top;printf("%d
",ct);
39     for (int i=1;i<=n;++i) printf("%d ",res[i]);puts("");
40     for (int i=1;i<=ct;++i) printf("%d ",cpt[i]);
41     return 0;
42 }

BZOJ 1053/Luogu P1463 [HAOI2007]反素数

将一个数n质因数分解,使n=∏pici(pi<pi+1,ci≠0),则ci≥ci+1.

可以发现前12个质数之积大于2×109,故对前12个质数打表,dfs+剪枝求出不超过n的x,使得g(x)在1~n内最大即可。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ll long long
 5 #define MX 12
 6 using namespace std;
 7 inline ll in(){
 8     ll x=0;bool f=0;char c;
 9     for (;(c=getchar())<'0'||c>'9';f=c=='-');
10     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
11     return f?-x:x;
12 }
13 const int pri[MX+1]={0,2,3,5,7,11,13,17,19,23,29,31};
14 ll n,mx,mp;
15 inline void dfs(int step,ll sum,int num,int fct){
16     if (step==MX){
17         if (num>mx||(num==mx&&sum<mp)) {mx=num;mp=sum;} return;
18     }ll prd=1;
19     for (int i=0;i<=fct;++i){
20         dfs(step+1,sum*prd,num+(num*i),i);
21         prd*=pri[step];if (sum*prd>n) return;
22     }
23 }
24 int main()
25 {
26     n=in();dfs(1,1,1,31);
27     printf("%d",mp);return 0;
28 }
原文地址:https://www.cnblogs.com/codingutopia/p/1806record1.html