20160327~20160402

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

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 }

题解:状压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 }

题解:思路很巧妙。先划分一下,第一步对≤√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 }

题解:首先将数组中所有小于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

时间: 2024-08-30 08:17:15

20160327~20160402的相关文章

[2016-03-27][HDU][1029][Ignatius and the Princess IV]

时间:2016-03-30 22:03:01 星期三 题目编号:[2016-03-27][HDU][1029][Ignatius and the Princess IV] 题目大意:给定n个数字,输出其中出现次数超过n/2的数字 #include <algorithm> #include <cstdio> using namespace std; const int maxn = 1E6 + 10; int a[maxn]; int main(){ int n; while(~sc

[2016-03-27][HDU][1260][Tickets]

时间:2016-03-27 22:37:37 星期日 题目编号:[2016-03-27][HDU][1260][Tickets] 遇到的问题:分钟数字,除以60以后还要模60 t / 60 % 60 #include <cstdio> #include <algorithm> using namespace std; typedef long long LL; const int maxk = 2000 + 10; int s[maxk],d[maxk]; int dp[maxk]

[2016-03-27][HDU][1087][Super Jumping! Jumping! Jumping!]

时间:2016-03-27 15:51:40 星期日 题目编号:[2016-03-27][HDU][1087][Super Jumping! Jumping! Jumping!] 分析:dp[i]表示跳到第i个位置,能拿到的最多分,则dp[i] = max(dp[i] , dp[j] + v[i]) 能从j跳到i 遇到的问题:排序之和,a[1].v <= a[2].v 而不是 a[1].v < a[2].v 所以还是需要判断一下价值 #include <algorithm> #in

[2016-03-27][HDU][1257][最少拦截系统]

时间:2016-03-27 14:51:35 星期日 题目编号:[2016-03-27][HDU][1257][最少拦截系统] 分析:贪心,每当不能拦截就增加一个拦截系统,可以发现,每个拦截系统拦截的高度比较和出现的顺序一样.即第二个系统始终比第一个系统拦截的高度高 #include <cstdio> using namespace std; int a[30000 + 10]; int main(){ int n,b,flg; while(~scanf("%d",&

[2016-03-27][HDU][1114][Piggy-Bank]

时间:2016-03-27 16:37:56 星期日 题目编号:[2016-03-27][HDU][1114][Piggy-Bank] 遇到的问题:注意f == e的情况,即dp[0] = 0; #include <cstring> #include <cstdio> #include<algorithm> using namespace std; int dp[10000 + 10]; int w[500 + 10],c[500 + 10]; int main(){

[2016-04-02][POJ][2253][Frogger]

时间:2016-04-02 17:55:33 星期六 题目编号:[2016-04-02][POJ][2253][Frogger] 题目大意:给定n个点的坐标,问从起点到终点的所有路径中,最大边的最小值是多少,即每一步至少是多少才能走到终点 分析: 方法1: 枚举出完全图,然后从起点跑一次Dijkstra算法,不过选点不再是选择起点到终点路径的点,而是起点到终点的路径中,边最大边最小的点,即d数组保存起点到当前点的路径中最大边的最小值, 最大边的最小值:u->v d[v] = min(d[i],m

[2016-04-02][POJ][2387][Til the Cows Come Home]

时间:2016-04-02 10:34:36 星期六 题目编号:[2016-04-02][POJ][2387][Til the Cows Come Home] 题目大意:给定n个节点和t条路,求n到1的最短路长度 分析:跑一次最短路即可 遇到的问题: 据说是多重边,如果是用邻接矩阵的就要更新最小值, 此题是先输入t,再输入n,输入的时候读错,无限WA- #include <queue> #include <cstring> #include <cstdio> using

用sql 生成2016年全年的日期

select to_char(日期,'yyyy-mm-dd') from( select to_date('2016-01-01','yyyy-mm-dd') + level 日期 from dual connect by level <=to_date('2016-12-31','yyyy-mm-dd')-to_date('2016-01-01','yyyy-mm-dd')); 结果: "日期""2016-01-02""2016-01-03&quo

你收藏了哪些藏品?

冷场恐惧症患者 ,尴尬癌晚期 1512 人赞同 比较冷门的一个,stereoview,中文大概翻译成立体相片.这是我无意中发现的,从此就掉进了坑里. 成套的我暂时只有这四盒,剩下的很多都是散张.看的时候把照片放在观影仪器上.由于利用的是左右眼视觉差,所以手机拍不出效果,当把眼睛靠近后,两幅照片会重合到一起,然后看到的效果是立体的,貌似最新一季的<夏洛特>里面出现过,有朋友看过后告诉我的,我自己并没有看. 照片是这样的.下面这个是underwood & underwood 公司出品的,是