20151105noip膜你赛bzoj3652 bzoj3653

Posted Konjak谷弱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20151105noip膜你赛bzoj3652 bzoj3653相关的知识,希望对你有一定的参考价值。

题目仿佛在讽刺我。。。

第一题:

题解:

考虑枚举区间右端点,维护所以左到当前的 and 和 or 。注意 and 每次变化至少有一个二进制位从1变 0,or 每次至少有一个位从0变 1,所以最多有log段不同的值。用两个链表维护这log个值,暴力计算答案即可。
O( nlogn)

我原本打的是一个树状数组的O(nlognlogn)算法。。然后被卡了。。只有50分。。

看了看奥爷爷的代码,发现他直接用一个链表同时维护and和or值,真奇怪啊不是(logn)^2吗。。然后男神说这个也是log级别的,因为两个区间不同只能是边界上跨越。

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 const int N=100010;
10 const LL mod=1000000007;
11 int n,al;
12 struct node{int last,next;LL t0,t1,sum;}a[N];
13 
14 int main()
15 {
16     // freopen("a.in","r",stdin);
17     // freopen("a.out","w",stdout);
18     freopen("value.in","r",stdin);
19     freopen("value.out","w",stdout);
20     scanf("%d",&n);
21     al=0;
22     int x,last=0;
23     LL ans=0;
24     for(int i=1;i<=n;i++)
25     {
26         scanf("%d",&x);
27         for(int j=last;j;j=a[j].last)
28         {
29             a[j].t0&=x;
30             a[j].t1|=x;    
31         }
32         a[++al].t0=x;a[al].t1=x;a[al].sum=1;
33         a[al].last=last;
34         if(last) a[last].next=al;
35         last=al;
36 
37         for(int j=last;j;j=a[j].last)
38         {
39             int p=a[j].last;
40             if(p && a[p].t0==a[j].t0 && a[p].t1==a[j].t1)
41             {
42                 a[p].sum+=a[j].sum;
43                 a[p].next=a[j].next;
44                 if(a[j].next) a[a[j].next].last=p;
45                 else last=p;//debug last=p not last=j
46             }
47         }
48         
49         for(int j=last;j;j=a[j].last)
50         {
51             ans=(ans+((((a[j].t0*a[j].t1)%mod)*a[j].sum)%mod))%mod;
52         }
53     }
54     printf("%I64d\\n",ans);
55     return 0;
56 }

 

第二题 bzoj3652

3652: 大新闻

Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge
Submit: 207  Solved: 106
[Submit][Status][Discuss]

Description

Input 两个整数n和p。p/100表示题目中描述的概率

Output 输出期望在模1000000007下的值


Sample Input

3 50

Sample Output

2

 

HINT

 


1<=N<=10^18

 
题解:
这题的数位dp达到我都昏了。。因为我打得挺复杂的。。
首先贴一个我的代码吧。
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 typedef long long LL;
  9 const LL mod=1000000007;
 10 const int N=100;
 11 LL n,m,p,bit[N],vis[N][2][2],cnt[N][2],f[N][2][2][2][2],g[N][2][2];
 12 int d[N];
 13 
 14 LL ad(LL x,LL y){return ((x+y)%mod+mod)%mod;}
 15 
 16 int find_vis(int x,int now,int flag)
 17 {
 18     if(x==0) return 1;
 19     if(vis[x][now][flag]!=-1) return vis[x][now][flag];
 20     int mx=1;if(flag || (x-1==0)) mx=d[x-1];
 21     LL ans=0;
 22     for(int i=0;i<=mx;i++)
 23     {
 24         ans=ad(ans,find_vis(x-1,i,flag&(i==d[x-1])));
 25     }
 26     vis[x][now][flag]=ans;
 27     // printf("x = %d  now = %d  flag = %d  = %d\\n",x,now,flag,ans); 
 28     return ans;
 29 }
 30 
 31 void find_cnt()
 32 {
 33     for(int i=1;i<=m;i++) cnt[i][0]=cnt[i][1]=bit[m];
 34     for(int i=m;i>=1;i--)
 35     {
 36         if(d[i]==0) 
 37         {
 38             for(int j=i-1;j>=1;j--) 
 39             {
 40                 cnt[j][0]=ad(cnt[j][0],-bit[i-1]);
 41                 cnt[j][1]=ad(cnt[j][1],-bit[i-1]);
 42             }
 43             cnt[i][1]=ad(cnt[i][1],-bit[i]);
 44             for(int j=i+1;j<=m;j++)
 45             {
 46                 cnt[j][d[j]]=ad(cnt[j][d[j]],-bit[i]);
 47             }
 48         }
 49     }
 50     
 51 }
 52 
 53 int dfs(int x,int now1,int now2,int flag1,int flag2) 
 54 {
 55     if(x==0) return 0;
 56     
 57     if(f[x][now1][now2][flag1][flag2]!=-1) return f[x][now1][now2][flag1][flag2];
 58     LL ans=0,now=0;
 59     int mx1=1;if(flag1 || (x-1==0)) mx1=d[x-1];
 60     int mx2=1;if(flag2 || (x-1==0)) mx2=d[x-1];
 61     if(now1+now2==1) ans=ad(ans,(vis[x][now1][flag1]*bit[x])%mod);
 62     for(int i=0;i<=mx1;i++)
 63     {
 64         if(flag2 && (i^1)>mx2) 
 65         {
 66             int f1=flag1&(i==d[x-1]);
 67             int f2=flag2&(0==d[x-1]);
 68             ans=ad(ans,dfs(x-1,i,0,f1,f2));
 69         }
 70         else 
 71         {
 72             int f1=flag1&(i==d[x-1]);
 73             int f2=flag2&((i^1)==d[x-1]);
 74             ans=ad(ans,dfs(x-1,i,i^1,f1,f2));
 75         }
 76     }
 77     f[x][now1][now2][flag1][flag2]=ans;
 78     // printf("f x = %d  now1 = %d  now2 = %d  flag1 = %d  flag2 = %d  ans = %d\\n",x,now1,now2,flag1,flag2,ans); 
 79     return ans;
 80 }
 81 
 82 int DFS(int x,int now,int flag)
 83 {
 84     if(x==0) return 0;
 85     if(g[x][now][flag]!=-1) return g[x][now][flag]; 
 86     int mx=1;if(flag || (x-1==0)) mx=d[x-1];
 87     LL ans=0;
 88     ans=ad(ans,(((vis[x][now][flag]*cnt[x][now^1])%mod)*bit[x])%mod);
 89     for(int i=0;i<=mx;i++)
 90     {
 91         ans=ad(ans,DFS(x-1,i,flag&(i==d[x-1])));
 92     }
 93     g[x][now][flag]=ans;
 94     // printf("g x = %d  now = %d  flag = %d  = %d\\n",x,now,flag,ans); 
 95     return ans;
 96 }
 97 
 98 LL quickpow(LL x,LL y)
 99 {
100     LL ans=1;
101     while(y) 
102     {
103         if(y&1) ans=(ans*x)%mod;
104         x=(x*x)%mod;
105         y/=2;
106     }
107     return ans;
108 }
109 
110 int main()
111 {
112     freopen("a.in","r",stdin);
113     // freopen("a.out","w",stdout);
114     // freopen("news.in","r",stdin);
115     // freopen("news.out","w",stdout);
116     scanf("%lld%lld",&n,&p);
117     LL x=n-1;m=0;
118     memset(d,0,sizeof(d));
119     while(x)
120     {
121         d[++m]=x%2;
122         x/=2;
123     }
124     bit[1]=1;
125     for(int i=2;i<=70;i++) bit[i]=(bit[i-1]*2)%mod;
126     memset(cnt,0,sizeof(cnt));
127     memset(vis,-1,sizeof(vis));
128     memset(f,-1,sizeof(f));
129     memset(g,-1,sizeof(g));
130     find_vis(m+1,0,1);
131     find_cnt();
132     
133     LL a1=dfs(m+1,0,0,1,1);
134     LL a2=DFS(m+1,0,1);
135     LL bn=quickpow(n%mod,mod-2);
136     LL bb=quickpow(100,mod-2);
137     LL ans=0;
138     
139     // for(int i=1;i<=3;i++)
140         // for(int j=0;j<=1;j++)
141             // printf("cnt %d %d = %I64d\\n",i,j,cnt[i][j]);
142         
143     ans=ad(ans,(((a1*bn)%mod)*((p*bb)%mod))%mod);
144     ans=ad(ans,(((((a2*bn)%mod)*bn)%mod)*(((100-p)*bb)%mod))%mod);
145     // printf("a1=%I64d a2=%I64d\\n",a1,a2);
146     printf("%lld\\n",ans);
147     return 0;
148 }
View Code

x表示当前填到哪一位。flag表示当前是否和边界重合。

dfs是做加密的情况,也就是确定当前填的x,然后让跟它异或的y尽量大。

DFS是做不加密的情况,也就是确定当前填的x,然后y所有可能都算上。

其中vis是维护到当前状态的方案数。

cnt是表示当前某个数位上是0或1的方案数。

 

好了还是这种做法太复杂了。。

学习了一下出题人的做法。

出题人题解:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 typedef long long LL;
 10 const LL mod=1000000007;
 11 const int N=110;
 12 LL n,m,p,bit[N],f[N][2][2],g[N][2][2];
 13 int a[N];
 14 
 15 LL quickpow(LL x,LL y)
 16 {
 17     LL ans=1;
 18     while(y)
 19     {
 20         if(y&1) ans=(ans*x)%mod;
 21         x=(x*x)%mod;
 22         y/=2;
 23     }
 24     return ans;
 25 }
 26 
 27 void dp_1()
 28 {
 29     memset(f,0,sizeof(f));
 30     memset(g,0,sizeof(g));
 31     g[0][1][1]=1;
 32     int now1,now2;
 33     for(int i=0;i<m;i++)
 34         for(int x1=0;x1<=1;x1++)
 35             for(int x2=0;x2<=1;x2++)
 36             {
 37                 if(g[i][x1][x2]==0) continue;
 38                 for(int j=0;j<=1;j++)
 39                 {
 40                     int k=j^1;
 41                     if(j>a[i+1] && x1) continue;
 42                     if(j==a[i+1] && x1) now1=1;
 43                     else now1=0;
 44                     if(k>a[i+1] && x2) k=0;
 45                     if(k==a[i+1] && x2) now2=1;
 46                     else now2=0;
 47                     g[i+1][now1][now2]=(g[i+1][now1][now2]+g[i][x1][x2])%mod;
 48                     f[i+1][now1][now2]=(f[i+1][now1][now2]+f[i][x1][x2]+((g[i][x1][x2]*(j^k))%mod*bit[i+1])%mod)%mod;
 49                 }
 50             }
 51 }
 52 
 53 
 54 void dp_2()
 55 {
 56     memset(f,0,sizeof(f));
 57     memset(g,0,sizeof(g));
 58     g[0][1][1]=1;
 59     int now1,now2;
 60     for(int i=0;i<m;i++)
 61         for(int x1=0;x1<=1;x1++)
 62             for(int x2=0;x2<=1;x2++)
 63             {
 64                 if(g[i][x1][x2]==0) continue;
 65                 for(int j=0;j<=1;j++)
 66                 {
 67                     if(j>a[i+1] && x1) continue;
 68                     if(x1 && j==a[i+1]) now1=1;
 69                     else now1=0;
 70                     for(int k=0;k<=1;k++)
 71                     {
 72                         if(k>a[i+1] && x2) continue;
 73                         if(x2 && k==a[i+1]) now2=1;
 74                         else now2=0;
 75                         g[i+1][now1][now2]=(g[i+1][now1][now2]+g[i][x1][x2])%mod;
 76                         f[i+1][now1][now2]=(f[i+1][now1][now2]+f[i][x1][x2]+(g[i][x1][x2]*(j^k))%mod*bit[i+1]%mod)%mod;
 77                     }
 78                 }
 79             }
 80 }
 81 
 82 
 83 int main()
 84 {
 85     freopen("a.in","r",stdin);
 86     // freopen("news.in","r",stdin);
 87     // freopen("news.out","w",stdout);
 88     scanf("%lld%lld",&n,&p);
 89     LL x=n-1,a1=0,a2=0;m=0;
 90     while(x)
 91     {
 92         a[++m]=x%2;
 93         x/=2;
 94     }
 95     for(int i=1;i<=m/2;i++) swap(a[i],a[m-i+1]);
 96     bit[m]=1;
 97     for(int i=m-1;i>=1;i--) bit[i]=(bit[i+1]*2)%mod;
 98     // for(int i=1;i<=m;i++) printf("%d ",a[i]);printf("\\n");
 99     
100     dp_1();
101     for(int i=0;i<=1;i++)
102         for(int j=0;j<=1;j++)
103             a1=(a1+f[m][i][j])%mod;
104     dp_2();
105     for(int i=0;i<=1;i++)
106         for(int j=0;j<=1;j++)
107             a2=(a2+f[m][i][j])%mod;
108     
109     LL bn=quickpow(n%mod,mod-2);
110     LL bb=quickpow(100,mod-xj膜你赛26

1111-1112膜你赛

Oct.17 膜你赛

Oct.20  膜你赛

膜你赛2018-9-7

CSP膜你赛大逃亡