Topcoder SRM523-527(DIV2)
来源:互联网 发布:老虎为什么数量少 知乎 编辑:程序博客网 时间:2024/06/12 21:42
SRM 523
现在有3种类型的积木,尺寸分别为1*1*1,1*1*2,1*1*3.如图所示.
现在给定一个1*1*w的底座和作品最高的高度,Lay博士可以在底座上搭积木完成作品,但是必须满足以下条件.积木必须放置在整数位置,且当一个积木能放在第i层,必须保证它的两个端点必须放置在已有积木之上.一个作品的高度就是积木的层数(除底座之外).两个作品视作不相同有两种情况:作品a的某一个位置有积木,b的相同位置没有;或a,b的某个位置都有积木,但是是不同类型的积木.
给出w,h,求出一共有多少种不同的方案.答案对1e9+7取模.
1≤w,h≤10.
下图是w=3,h=2的例子.
思路:
<1>本题的w<=10所以可以所以用二进制压缩状态
<2>先计算出对于同一种状态的积木有多少种不同的组成方式
<3>状态的转移dp[i][x1]+=dp[i-1][x2]*F[x1][x2];(对于一层状态为x2 的积木有N个方法使其转移成x1)
//对于一层积木例如11101101;它的组成的可能为sum[3]*sum[2]*sum[1]; //通过递推很容易得到 sum[0]=sum[1]=1;sum[2]=2;sum[3]=4; for(int i=4;i<=10;i++)sum[i]=sum[i-1]+sum[i-2]+sum[i-3];
//预处理F for(int i=1;i<1<<W;i++)for(int j=1;j<1<<W;j++){ while(x1||x2)a[++num]=x1%2,b[num]=x2%2,x1/=2,x2/=2; //如果a[i]有而b[i]没有只有一种情况合法即 //11111 //10111 //于是这个111就确定了F[11111][10111]=F[00011][10111]*1; for(int c=1;c<=W;c++)if(a[c]&&!b[c]){ if(a[c+1]&&a[c-1]&&b[c-1]&&b[c+1])a[c]=a[c+1]=a[c-1]=0; else ok=0; }if(ok){ F[i][j]=1;cnt=0; for(int c=1;c<=W+2;c++){ if(a[c])cnt++; else F[i][j]*=sum[cnt],cnt=0; } } }
for(int i=1;i<1<<W;i++) dp[1][i]=val[i]; for(int i=1;i<H;i++) for(int x=1;x<1<<W;x++) for(int y=1;y<1<<W;y++) dp[i+1][x]=(dp[i+1][x]+dp[i][y]*F[x][y])%P; for(int i=1;i<=H;i++) for(int x=1;x<1<<W;x++) ans=(ans+dp[i][x])%P; return ans;}
SRM 524
你的任务是找到一个最小的正整数x,使得:
x是N的倍数。
x的十进制表示中不存在被禁用的数字。
现在告诉你哪些数字被禁用。
如果无解,返回一个字符串”IMPOSSIBLE”。
如果解位数小于9,直接返回表示该数的字符串。
否则,你只需要给出一个省略形式的解,形式如”abc…def(g digits)”,其中abc表示该数开头的三个数字,def表示该数结尾的三个数字,g表示这个数字的位数。
(N<=10000)
思路:
<1>使用BFS从小到大枚举所以的数
<2>很容易发现对于一个数A其有贡献的值即为B=A % N 所以已经出现过的B就无需记录了
<3>(A*10+K)%N==(B*10+k)%N;
struct node{ //a表前3位,b表最后的3位 short a,b,len,res; int p//原数; node(){a=0,b=0,len=0,res=0,p=0;} void pt(){ if(len<=8)printf("%d",p); else printf("%d+"..."+%d+"("+%d+" digits)",a,b,len); } };
for(int i=0;i<x.size();i++)mark[x[i]]=1; for(int i=0;i<10;i++)if(!mark[i])c[num++]=i; node tmp;tmp.len=1; for(int i=0;i<num;i++) if(c[i]){ tmp.p=tmp.b=c[i]; tmp.res=c[i]%n; Q.push(tmp); }node nx,nw; int l,r,b,ok=0; while(!Q.empty()){ nw=Q.front();Q.pop(); if(nw.res==0){ nw.pt();return 0; }nw.len++; if(nw.len<=8)ok=1; if(nw.a<=99)nw.a=nw.a*10+nw.b/100; nx=nw; b=nw.b*10%1000; r=nw.res*10; for(int i=0;i<num;i++){ nx=nw; nx.res=(r+c[i])%n; nx.b=b+c[i]; if(ok)nx.p=nx.p*10+c[i]; if(hav[nx.res])continue; hav[nx.res]=1; Q.push(nx); } }puts("IMPOSSIBLE");}
SRM 525
现在有一个3*3的矩形,和两行关于矩形的信息rowStrings和columnStrings:
•0<=i<=2,S[i][0]+S[i][1]+S[i][2]= rowStrings[i].
•0<=i<=2,S[0][i]+S[1][i]+S[2][i]= columnStrings[i];
例如下述矩形的rowStrings[]={“123”,456”,789”}; columnStrings[]={“147”,”258”,”369”};
现给出rowStrings和columnStrings,询问满足条件的矩形个数;
0<= rowStrings和columnStrings内字符串的长度 <=50;
思路:
<1>由于本题的数据小可以直接枚举其中几个格子中的元素的个数
<2>显然只需要枚举其中4个即可
int main(){ if(A[0].S+A[1].S+A[2].S!=B[0].S+B[1].S+B[2].S)return 0; long long ans=0; for(int x1=0;x1<=A[0].S;x1++) for(int x2=0;x2<=A[0].S-x1;x2++) for(int x4=0;x4<=A[1].S;x4++) for(int x5=0;x5<=A[1].S-x4;x5++){ int x7=B[0].S-x1-x4,x8=B[1].S-x5-x2; if(B[0].substr(0,x1)+B[1].substr(0,x2)+B[2].substr(0,A[0].S-x1-x2)!=A[0])continue; if(B[0].substr(x1,x4)+B[1].substr(x2,x5)+B[2].substr(A[0].S-x1-x2,A[1].S-x4-x5)!=A[1])continue; if(B[0].substr(x4+x1,x7)+B[1].substr(x5+x2,x8)+B[2].substr(A[1].S-x4-x5+A[0].S-x1-x2,A[2].S-x7-x8)!=A[2])continue; ans++; }return ans; }
SRM 527
定义一个数的Luckiness值为该数字中4出现的个数与7出现的个数之差。
给定A,B,求A到B区间的数的Luckiness值之和。(1<=A,B<=2,000,000,000)
思路
<1>ans=val[B]-val[A-1];
<2>一位一位地枚举时注意判断这位数是否需要小于A的该位(即之前的即为均和A逐位相等)
<3>对于一个数只有几个信息是有用的
void dfs(int x,int a,int b,int f){ if(!x)return abs(a-b); int mx=f?c[x]:9,ans=0; for(int i=0;i<=mx;i++){ if(i==4)ans+=dfs(x+1,a+1,b,f&&mx==i); if(i==7)ans+=dfs(x+1,a,b+1,f&&mx==i); ans+=dfs(x+1,a,b,f&&mx==i); }}
int main(){ while(A)c[++num]=A%10,A/=10; ans=dfs(num,0,0,1);}
SRM 527
现在有n种面值的零钱,对于0~n-1中的每个i,有一个面值为2^i的硬币.现在给出整数n,sum,cnt.你的任务找出一种硬币组合的方案使得硬币个数为cnt,硬币面值总和为sum.请输出每个面值硬币的数量.若有多种方案,输出字典序最小的.
1≤n≤60,1≤sum,cnt≤10^18
vector<long long>res(n);//定义vector的[0,n-1] ll use=0; for(int i=0;i<n;i++){ if(sum&1){res[i]=1;use++;} else res[i]=0; sum>>=1;if(!sum)break; } if(sum>0)use+=sum*2,res[n-1]+=sum*2; if(use>cnt)res.clear(); ll res=cnt-use; for(int i=n-1;i>0&&res;i--){ ll b=min(a,res[i]); res[i]-=b; res[i-1]+=b*2; res-=b; }return res; }
- Topcoder SRM523-527(DIV2)
- SRM523 div2 500 CountingSeries
- topcoder-srm610-div2-550(暴力乱搞)
- 【Topcoder SRM523】【meet in the middle】 AlphabetPaths 搜索
- topcoder SRM 513 DIV2
- TopCoder SRM 543 DIV2
- topcoder 544 div2
- Topcoder SRM548 div2
- topcoder-srm-233-div2
- Topcoder SRM Div2 Level2
- topcoder-595-div2
- topcoder srm606 div2
- topcoder srm607 div2
- TopCoder SRM 144 div2
- TOPCODER SRM 612 DIV2
- TOPCODER SRM 613 DIV2
- TopCoder SAM 631 DIV2
- [Topcoder]SRM632 div2 题解
- Kafka文件存储机制那些事
- codeforces437b
- 清橙 A1485 Catch The Penguins 抓企鹅(张闻涛)
- LeetCode 485. Max Consecutive Ones
- 今天开通了CSDN微博,希望记录自己学习编程的点滴
- Topcoder SRM523-527(DIV2)
- 双向链表的C++实现
- 四、java常见日期函数
- linux学习笔记(系统管理命令)
- 这20个正则表达式,让你少写1,000行代码
- vue2.0从入门到入坑
- Activity跳转方式总结
- Jenkins使用shell脚本部署到远程服务器步骤
- Tomcat+MyEclipse 动态资源开发及部署