【2018.11.8】小迟的比赛 / Yuno like cake / 格子填数

题目

$noip$ 欢乐赛真是欢乐,除了不欢乐的方面以外我都很欢乐


T1

鸡汤题目,故意输对后面的胜率又没有影响,为什么要故意输呢?

所以第二个决策是凑字用的,这题就是朴素递推概率,最后乘结果权值计算期望。

 1 #include<cctype>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 inline int read(){
 9     int x=0; bool f=1; char c=getchar();
10     for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
11     for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
12     if(f) return x;
13     return 0-x;
14 }
15 #define N 1001
16 int n;
17 double p[N][N],f[N][N];
18 int main(){
19     freopen("game.in","r",stdin);
20     freopen("game.out","w",stdout);
21     n=read();
22     int i,j;
23     f[0][0]=1;
24     for(i=1;i<=n;++i){
25         cin>>p[i][j]; f[i][0]=f[i-1][0]*(1-p[i][j]);
26         for(j=1;j<i;++j){
27             cin>>p[i][j];
28             f[i][j]=f[i-1][j-1]*p[i][j-1]+f[i-1][j]*(1-p[i][j]);
29         }
30         f[i][j]=f[i-1][j-1]*p[i][j-1];
31     }
32     double ans=0;
33     for(i=1;i<=n;++i) ans+=f[n][i]*i;
34     printf("%.2f",ans);
35     return 0;
36 }
View Code

T2

原题……在日本竞赛书上看到过……

把 $40$ 个数平分成两半,枚举其中一半的选取情况,然后在另一半中二分出能取的最大的剩下部分。时间复杂度 $O(2^{20}*log(2^{20}))$。

 1 #include<cctype>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define ll long long
 8 using namespace std;
 9 inline int read(){
10     int x=0; bool f=1; char c=getchar();
11     for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
12     for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
13     if(f) return x;
14     return 0-x;
15 }
16 
17 int n,x;
18 ll v[1<<21],l[1<<21],r[1<<21];
19 int main(){
20     freopen("cake.in","r",stdin);
21     freopen("cake.out","w",stdout);
22     n=read(),x=read();
23     int i,to=n>>1;
24     for(i=1;i<=to;++i) v[1<<(i-1)]=read();
25     int l_len=1<<to, r_len=1<<(n-to), tmp;
26     for(i=1;i^l_len;++i) tmp=i&(i-1), l[i]=v[i^(i&tmp)]+l[i&tmp];
27     for(i=1;i<=n-to;++i) v[1<<(i-1)]=read();
28     for(i=1;i^r_len;++i) tmp=i&(i-1), r[i]=v[i^(i&tmp)]+r[i&tmp];
29     sort(l+1,l+l_len);
30     sort(r+1,r+r_len);
31     int wz; ll ans=0;
32     for(i=0;i^l_len;++i){
33         if(l[i]>x) continue;
34         wz=upper_bound(r+1,r+r_len,x-l[i])-r-1;
35         ans=max(ans,l[i]+r[wz]);
36         //printf("go:%d %d %d %d
",i,wz,l[i],r[wz]);
37     }
38     printf("%lld",x-ans);
39     return 0;
40 }
View Code

T3

CXM 之前讲过……

矩阵不相交的情况 和 相交而且数不相同的情况也很好做,直接用小的限制覆盖掉大的限制就完了。

两个矩阵相交而且数相同的话,会麻烦一点,因为在重叠区域放一个数就可以满足两个限制,而在两矩阵不相交的地方,需要两边各放一个才行。

而且更多数相同的矩阵相交的话,计算就更复杂了。

那怎么算?容斥?

其实可以把相交且数相同的矩阵连通块分割,使任意相邻两块的覆盖层数不相等,然后用二进制数给每个部分按照覆盖情况进行二进制编号,做 $dp$。简单地说就是状压 $dp$。

  1 #include<bits/stdc++.h>
  2 #define rep(i,x,y) for(register int i=(x);i<=(y);i++)
  3 #define dwn(i,x,y) for(register int i=(x);i>=(y);i--)
  4 #define maxn 51
  5 #define maxk 10010
  6 #define maxs ((1<<10)+5)
  7 #define LL long long
  8 using namespace std;
  9 int read()
 10 {
 11     int x=0,f=1;char ch=getchar();
 12     while(!isdigit(ch)&&ch!='-')ch=getchar();
 13     if(ch=='-')f=-1,ch=getchar();
 14     while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
 15     return x*f;
 16 }
 17 void write(int x)
 18 {
 19     int f=0;char ch[20];
 20     if(!x){putchar('0'),putchar('
');return;}
 21     if(x<0)x=-x,putchar('-');
 22     while(x)ch[++f]=x%10+'0',x/=10;
 23     while(f)putchar(ch[f--]);
 24     putchar('
');
 25 }
 26 typedef struct quest{int l,r,u,d,k;}que;
 27 que q[maxn];
 28 const int mod=1e9+7; 
 29 int f[maxs][maxs],sum;//,sum;
 30 int full,fulls,r,c,n,m,g[maxn][maxn],siz[maxs],tox[maxk],toy[maxk],num[maxn][maxn],bacx[maxn],bacy[maxn],extx[maxn],exty[maxn],cntx,cnty,nowx=2,nowy=2;
 31 int mul(int x,int y)
 32 {
 33     int ans=1;
 34     while(y)
 35     {
 36         if(y&1)ans=(int)(((LL)ans*(LL)x)%((LL)mod));
 37         x=(int)(((LL)x*(LL)x)%((LL)mod)),y>>=1;
 38     }
 39     return ans;
 40 }
 41 void print(int x)
 42 {
 43     rep(i,1,n)cout<<((x&(1<<(i-1)))?1:0);return;
 44 }
 45 int main()
 46 {
 47     freopen("grid.in","r",stdin);
 48     freopen("grid.out","w",stdout);
 49     memset(bacx,-1,sizeof(bacx));
 50     memset(bacy,-1,sizeof(bacy));
 51     r=read(),c=read(),m=read(),n=read();
 52     bacx[1]=bacy[1]=1;tox[1]=toy[1]=1;
 53     fulls=(1<<n)-1;
 54     rep(i,1,n)
 55     q[i].l=read(),q[i].u=read(),q[i].r=read(),q[i].d=read(),q[i].k=read(),
 56     extx[++cntx]=q[i].l,extx[++cntx]=q[i].r,exty[++cnty]=q[i].u,exty[++cnty]=q[i].d;
 57     sort(extx+1,extx+cntx+1),sort(exty+1,exty+cnty+1);
 58     extx[0]=1;
 59     rep(i,1,cntx)
 60     {
 61         if(extx[i]!=extx[i-1]){if(extx[i]-extx[i-1]>1)nowx++;bacx[nowx]=extx[i],tox[extx[i]]=nowx,nowx++;}
 62     }
 63     if(bacx[nowx-1]!=r){if(r-extx[cntx]>1)nowx++;bacx[nowx]=r,tox[r]=nowx;}
 64     else nowx--;
 65     exty[0]=1;
 66     rep(i,1,cnty)
 67     {
 68     //    cout<<exty[i]<<endl;
 69         if(exty[i]!=exty[i-1]){if(exty[i]-exty[i-1]>1)nowy++;bacy[nowy]=exty[i],toy[exty[i]]=nowy,nowy++;}
 70     }
 71     if(bacy[nowy-1]!=c){if(c-exty[cnty]>1)nowy++;bacy[nowy]=c,toy[c]=nowy;}
 72     else nowy--;
 73     rep(i,1,nowx)
 74         rep(j,1,nowy)
 75         {
 76             int numx,numy;
 77             if(bacx[i]!=-1)numx=1;
 78             else numx=bacx[i+1]-bacx[i-1]-1;
 79             if(bacy[j]!=-1)numy=1;
 80             else numy=bacy[j+1]-bacy[j-1]-1;
 81             num[i][j]=numx*numy;
 82         }
 83     rep(i,1,n)
 84     {
 85         rep(j,tox[q[i].l],tox[q[i].r])
 86             rep(k,toy[q[i].u],toy[q[i].d])
 87                 g[j][k]+=(1<<(i-1));
 88     }
 89     rep(i,1,nowx)
 90     {
 91         rep(j,1,nowy)
 92         {
 93             siz[g[i][j]]+=num[i][j];
 94             full=max(full,g[i][j]);
 95         }
 96     }
 97     f[0][0]=mul(m,siz[0]);
 98     rep(i,0,full-1)
 99     {
100         rep(j,0,fulls)
101         {
102             int limit=m,num=0;
103             rep(k,1,n)if((i+1)&(1<<(k-1)))limit=min(limit,q[k].k);
104             rep(k,1,n)if(((i+1)&(1<<(k-1)))&&q[k].k==limit)num|=(1<<(k-1));
105             f[i+1][j]=(int)(((LL)f[i+1][j]+(LL)f[i][j]*(LL)mul(limit-1,siz[i+1]))%((LL)mod));
106             f[i+1][j|num]=(int)(((LL)f[i+1][j|num]+(LL)f[i][j]*(((LL)mul(limit,siz[i+1])-(LL)mul(limit-1,siz[i+1])+(LL)mod)%((LL)mod)))%((LL)mod));
107         }
108     }
109     write(f[full][fulls]);
110     return 0;
111 }
112 /*
113 2 3 2 1
114 1 2 2 3 2
115 */
116 /*
117 3 6 3 2
118 1 2 2 3 2
119 1 3 3 6 1
120 */
121 /*
122 7 11 5 4
123 2 2 4 4 3
124 3 3 5 5 2 
125 4 4 5 9 3 
126 1 7 6 8 1
127 */
SYF
 1 #include<bits/stdc++.h>
 2 typedef long long i64;
 3 const int P=1e9+7;
 4 int T,h,w,m,n;
 5 int xs[33],ys[33],xp,yp,vs[33],vp,ts[33];
 6 int rc[33][5],mv[33][33],as[33][33];
 7 void mins(int&a,int b){if(a>b)a=b;}
 8 int pw(int a,int n){
 9     int v=1;
10     for(;n;n>>=1,a=i64(a)*a%P)if(n&1)v=i64(v)*a%P;
11     return v;
12 }
13 int main(){
14     int ans=0;
15     scanf("%d%d%d%d",&h,&w,&m,&n);
16     xp=yp=vp=0;
17     xs[xp++]=1;
18     xs[xp++]=h+1;
19     ys[yp++]=1;
20     ys[yp++]=w+1;
21     vs[vp++]=m;
22     for(int i=0;i<n;++i){
23         for(int j=0;j<5;++j)scanf("%d",rc[i]+j);
24         xs[xp++]=rc[i][0];
25         xs[xp++]=rc[i][2]+1;
26         ys[yp++]=rc[i][1];
27         ys[yp++]=rc[i][3]+1;
28         vs[vp++]=rc[i][4];
29         vs[vp++]=rc[i][4]-1;
30     }
31     std::sort(xs,xs+xp);
32     xp=std::unique(xs,xs+xp)-xs-1;
33     std::sort(ys,ys+yp);
34     yp=std::unique(ys,ys+yp)-ys-1;
35     std::sort(vs,vs+vp);
36     vp=std::unique(vs,vs+vp)-vs;
37     for(int i=0;i<xp;++i)
38         for(int j=0;j<yp;++j)as[i][j]=(xs[i+1]-xs[i])*(ys[j+1]-ys[j]);
39     for(int t=0;t<n;++t){
40         rc[t][0]=std::lower_bound(xs,xs+xp,rc[t][0])-xs;
41         rc[t][2]=std::lower_bound(xs,xs+xp,rc[t][2]+1)-xs;
42         rc[t][1]=std::lower_bound(ys,ys+yp,rc[t][1])-ys;
43         rc[t][3]=std::lower_bound(ys,ys+yp,rc[t][3]+1)-ys;
44         rc[t][4]=std::lower_bound(vs,vs+vp,rc[t][4])-vs;
45     }
46     for(int S=0;S<(1<<n);++S){
47         for(int i=0;i<xp;++i)
48             for(int j=0;j<yp;++j)mv[i][j]=vp-1;
49         int s=1;
50         for(int t=0;t<n;++t){
51             int v=rc[t][4];
52             if(S>>t&1)s=-s,--v;
53             for(int i=rc[t][0];i<rc[t][2];++i)
54                 for(int j=rc[t][1];j<rc[t][3];++j)mins(mv[i][j],v);
55         }
56         for(int i=0;i<vp;++i)ts[i]=0;
57         for(int i=0;i<xp;++i)
58             for(int j=0;j<yp;++j)ts[mv[i][j]]+=as[i][j];
59         for(int i=0;i<vp;++i)s=i64(s)*pw(vs[i],ts[i])%P;
60         ans=(ans+s)%P;
61     }
62     printf("%d
",(ans+P)%P);
63     return 0;
64 }
std(好像是另类做法)

另外 $wxj$ 用扫描线过了……

相关推荐