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 JudgeSubmit: 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 }
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