码迷,mamicode.com
首页 > 其他好文 > 详细

20160327~20160402

时间:2016-04-03 12:59:47      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

蒟蒻太弱了,一星期刷这么少。

20160329:

1、bzoj1087 http://www.lydsy.com/JudgeOnline/problem.php?id=1087

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 using namespace std;
 6 
 7 long long x[100][10000],y[100][10000],n,k;
 8 inline bool bit(int x,int y){return x&(1<<(y-1));}
 9 inline int set(int x,int y,bool z){
10     if(z)return x|(1<<(y-1));else return x&((1<<(n+1))-1-(1<<(y-1)));
11 }
12 int main(){
13     scanf("%d%d",&n,&k); x[k][0]=1;
14     inc(i1,1,n)inc(j1,1,n){
15         inc(i2,0,k)inc(j2,0,(1<<(n+1))-1)y[i2][j2]=0;
16         inc(i2,0,k)inc(j2,0,(1<<(n+1))-1){
17             if(i2&&(j1==1||(! bit(j2,j1-1)))&&(i1==1||(! bit(j2,j1)))&&(i1==1||j1==1||(! bit(j2,n+1)))&&(j1==n||(! bit(j2,j1+1))))
18                 y[i2-1][set(set(j2,n+1,bit(j2,j1)),j1,1)]+=x[i2][j2];
19             y[i2][set(set(j2,n+1,bit(j2,j1)),j1,0)]+=x[i2][j2];
20         }swap(x,y);
21     }
22     long long ans=0; inc(i,0,(1<<(n+1))-1)ans+=x[0][i]; printf("%lld",ans);
23     return 0;
24 }
View Code

题解:状压dp。我的做法是像插头dp那样保存当前列右侧的上一行和当前列左侧的当前行的情况,同时加一列存左上角的状态,逐格递推,滚动掉行列的状态表示。过倒是过了然而是状态版上的倒数第一。我状压dp递推的时候不知道怎么省状态,可能写记忆化搜索会快一些,但就不能滚动了。

20160331:

2、bzoj1257 http://www.lydsy.com/JudgeOnline/problem.php?id=1257

 

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #define inc(i,j,k) for(long long i=j;i<=k;i++)
 6 using namespace std;
 7 
 8 int main(){
 9     long long n,k; scanf("%lld%lld",&n,&k); long long ans=0;
10     long long sz=(long long)sqrt(k)+1;
11     if(n<=sz){
12         inc(i,1,n)ans+=k%i;
13     }else{
14         inc(i,1,sz)ans+=k%i;
15         inc(j,1,k/sz){
16             long long l=max(k/(j+1)+1,sz+1),r=min(min(k/j,k),n); if(l>r)continue;
17             ans+=(k*(r-l+1)-j*(l+r)*(r-l+1)/2);
18         }
19         if(n>k)ans+=k*(n-k);
20     }
21     printf("%lld",ans);
22     return 0;
23 }
View Code

题解:思路很巧妙。先划分一下,第一步对≤√k的n暴力求。因为a%b也对于a-a div b(用pascal的术语,表整除)*b,所以第二步对于1到√k的每个数i,求一个区间[l,r]使得区间里每个数被k整除后商为i,然后就可以用数列求和公式求k div [l,r]*[l,r]的和,再用k减后做个累加即可,但要注意区间不要和之前在第一步求过的重叠。对大于k的n直接做乘法,因为一个数%大于自己的数等于自己。

20160401:

3、bzoj1303 http://www.lydsy.com/JudgeOnline/problem.php?id=1303

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define dec(i,j,k) for(int i=j;i>=k;i--)
 6 using namespace std;
 7 
 8 int l[400000],r[400000],s,n,b,a[200000],p;
 9 int main(){
10     scanf("%d%d",&n,&b); 
11     inc(i,1,n){
12         int a1; scanf("%d",&a1); if(a1==b)a[i]=0,p=i; if(a1<b)a[i]=-1; if(a1>b)a[i]=1;
13     }
14     l[p+1]=0; dec(i,p,1)l[i]=l[i+1]+a[i];
15     memset(r,0,sizeof(r)); s=0; inc(i,p,n)s=s+a[i],r[s+n]++;
16     int ans=0; inc(i,1,p)ans+=r[-l[i]+n];
17     printf("%d",ans);
18 }
View Code

题解:首先将数组中所有小于b的数置为-1,等于的置为0,大于的置为1。然后对b及其右边的数的前缀和(b的位置到该位置所有数的和)出现个数建一个数组r,对b左边的数的每个后缀和(该位置到b的位置所有数的和)的相反数在r中的数相乘就是答案。实际上,这种把数转化成1、-1、0的方法十分常用,但是我不会。

4、bzoj1143 http://www.lydsy.com/JudgeOnline/problem.php?id=1143

见专门题解:网络流

5、bzoj1202 http://www.lydsy.com/JudgeOnline/problem.php?id=1202

20160327~20160402

标签:

原文地址:http://www.cnblogs.com/YuanZiming/p/5349516.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!