topcoder srm 706 div1
1、给定一个迷宫,点号表示不可行,井号表示可行。现在可以改变其中的一些井号的位置。问最少改变多少个井号可以使得从左上角到右下角存在路径。
思路:设高为$n$,宽为$m$,若井号的个数$S$小于$n+m-1$则无解。否则最多改变$n+m-1$个井号即可。令$f[x][y][k]$表示现在到达位置$(x,y)$且中途经过的点号格子数为$k$时最少经过了多少井号格子。这样进行搜索即可。搜过过程中,应该满足$k\leq n+m-1$且$k+f[x][y][k]\leq S$。
- #include <iostream>
- #include <set>
- #include <stdio.h>
- #include <queue>
- #include <algorithm>
- #include <string.h>
- using namespace std;
- const int N=20;
- int f[N][N][N+N];
- int inq[N][N][N+N];
- int h[N][N][N+N];
- const int dx[]={0,0,1,-1};
- const int dy[]={1,-1,0,0};
- struct node
- {
- int x,y,p;
- node(){}
- node(int _x,int _y,int _p):
- x(_x),y(_y),p(_p) {}
- };
- queue<node> Q;
- void add(int x,int y,int p,int c)
- {
- if(!h[x][y][p]||f[x][y][p]>c)
- {
- h[x][y][p]=1;
- f[x][y][p]=c;
- if(!inq[x][y][p])
- {
- inq[x][y][p]=1;
- Q.push(node(x,y,p));
- }
- }
- }
- class MovingCandies
- {
- public:
- int minMoved(const vector<string> t)
- {
- const int n=(int)t.size();
- const int m=(int)t[0].size();
- int S=0;
- for(int i=0;i<n;++i) for(int j=0;j<m;++j) S+=t[i][j]=='#';
- if(S<n+m-1) return -1;
- if(t[0][0]=='.') add(0,0,1,0);
- else add(0,0,0,1);
- while(!Q.empty())
- {
- const int x=Q.front().x;
- const int y=Q.front().y;
- const int p=Q.front().p;
- const int c=f[x][y][p];
- Q.pop();
- inq[x][y][p]=0;
- if(x==n-1&&y==m-1) continue;
- for(int d=0;d<4;++d)
- {
- const int xx=x+dx[d];
- const int yy=y+dy[d];
- if(xx>=0&&xx<n&&yy>=0&&yy<m)
- {
- const int pp=p+(t[xx][yy]=='.');
- const int cc=c+(t[xx][yy]=='#');
- if(pp>n+m-1||pp+cc>S) continue;
- add(xx,yy,pp,cc);
- }
- }
- }
- for(int i=0;i<=n+m-1;++i)
- {
- if(h[n-1][m-1][i]) return i;
- }
- return -1;
- }
- };
2、给定一个整数数组,每个数字可以被替换成字符ABC中的一个,相同的数组必须被相同的字符替换。问在被任意替换得到的所有不同的字符串中,包含子列ABC的串有多少个。
思路:一个简单的思路是分别枚举第一个A、第一个B、第一个C出现的位置,这样整个串被分成4部分,第一部分中不能出现A,第二部分不能出现B,第三部分不能出现C。这样复杂度是$O(N^{3})$。现在只枚举第一个A第一个B,然后后面字符任意的总数为$X$,不包含C的总数为$Y$,那么此次枚举对答案的贡献为$X-Y$。这样是$O(N^{2})$的复杂度。实现如代码所示。其中$f[i][j]=0$表示数字$i$可以被替换成字符$j$,$j=0$表示A,$j=1$表示B,$j=2$表示C。$tot[j]$表示有多少种数字有$j$种替换方式。
- #include <string.h>
- #include <stdio.h>
- #include <vector>
- using namespace std;
- const int mod=1000000007;
- const int N=3005;
- int p[4][N];
- int tot[4];
- int f[N][4];
- int appears[N];
- class MappingABC
- {
- void init()
- {
- for(int i=0;i<4;++i)
- {
- p[i][0]=1;
- for(int j=1;j<N;++j) p[i][j]=((long long)p[i][j-1]*i%mod);
- }
- }
- void clear()
- {
- memset(f,0,sizeof(f));
- memset(tot,0,sizeof(tot));
- }
- int get()
- {
- int ans=1;
- for(int i=0;i<4;++i) ans=((long long)ans*p[i][tot[i]]%mod);
- return ans;
- }
- int cal(int x)
- {
- int c=0;
- for(int i=0;i<3;++i) if(f[x][i]==0) ++c;
- return c;
- }
- void add(int x,int y)
- {
- --tot[cal(x)];
- ++f[x][y];
- ++tot[cal(x)];
- }
- void sub(int x,int y)
- {
- --tot[cal(x)];
- --f[x][y];
- ++tot[cal(x)];
- }
- public:
- int countStrings(vector<int> t)
- {
- const int n=(int)t.size();
- for(int i=0;i<n;++i) appears[t[i]]=1;
- init();
- int ans=0;
- const int A=0,B=1,C=2;
- for(int k=0;k<2;++k)
- {
- const int NO_C=k==1;
- for(int a=0;a<n;++a)
- {
- clear();
- for(int i=0;i<N;++i) if(appears[i]) ++tot[3];
- for(int i=0;i<a;++i) add(t[i],A);
- add(t[a],B);
- add(t[a],C);
- if(NO_C)
- {
- for(int i=a+1;i<n;++i) add(t[i],C);
- }
- for(int b=a+1;b<n;++b)
- {
- if(NO_C) sub(t[b],C);
- add(t[b],A);
- add(t[b],C);
- if(NO_C) ans=(ans-get())%mod;
- else ans=(ans+get())%mod;
- sub(t[b],A);
- sub(t[b],C);
- add(t[b],B);
- }
- }
- }
- if(ans<0) ans+=mod;
- return ans;
- }
- };
3、构造一个长度为n的数组$A$,使得$A_{i}$和$A_{j}$互质当且仅当$|i-j|=1$。n不大于500。数组中每个数字大于1小于等于$10^{18}$。
思路:我看到的第一种思路是随机。比如有32个素数,$A$中的每个数字由11位素数构成,每次随机选取11个,判断是否可行。第二种思路如下代码所示。假设当前长度$N=2^{k}$,那么每次处理前,前$N/4$的数字是符合要求的。处理之后前$N/2$是符合要求的。为方便说明,假设整个$N$分为四段,$A,B,C,D$,一开始$A$符合要求。且$A$中的奇数位置跟 $B$的偶数位置满足不互质,$A$中的偶数位置跟 $B$的奇数位置满足不互质。那么只要处理使得$A$中的奇数位置跟 $B$的奇数位置满足不互质,$A$中的偶数位置跟 $B$的偶数位置满足不互质即可。
- #include <string.h>
- #include <stdio.h>
- #include <vector>
- using namespace std;
- int check(int x)
- {
- for(int i=2;i*i<=x;++i) if(x%i==0) return 0;
- return 1;
- }
- vector<int> prime;
- int id;
- void init()
- {
- for(int i=2;i<100;++i) if(check(i)) prime.push_back(i);
- }
- long long a[1024];
- void add(int i,int t)
- {
- a[i]*=t;
- }
- class CoprimeNeighbors
- {
- public:
- vector<long long> findAny(int n)
- {
- init();
- for(int i=0;i<4;++i) a[i]=1;
- int N=8;
- while(N/4<n)
- {
- const int d=N>>1;
- const int M=d-1;
- for(int i=0;i<=M;++i) a[i+d]=a[i];
- const int p=prime[id++];
- const int q=prime[id++];
- const int LM=M>>1;
- for(int i=0;i<=LM;i+=2) add(i,p),add(i+d,q);
- for(int i=LM+2;i<=M;i+=2) add(i,p),add(i+d,q);
- for(int i=1;i<=LM;i+=2) add(i,q),add(i+d,p);
- for(int i=LM+3;i<=M;i+=2) add(i,q),add(i+d,p);
- N<<=1;
- }
- const int p=prime[id++];
- const int q=prime[id++];
- for(int i=0;i<n;i+=2) add(i,p);
- for(int i=1;i<n;i+=2) add(i,q);
- vector<long long> ans;
- for(int i=0;i<n;++i) ans.push_back(a[i]);
- return ans;
- }
- };
topcoder srm 706 div1的更多相关文章
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
- Topcoder Srm 726 Div1 Hard
Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...
- topcoder srm 714 div1
problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...
- topcoder srm 738 div1 FindThePerfectTriangle(枚举)
Problem Statement You are given the ints perimeter and area. Your task is to find a triangle wi ...
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串
Problem Statement The Happy Letter game is played as follows: At the beginning, several players ...
- Topcoder SRM 584 DIV1 600
思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...
- TopCoder SRM 605 DIV1
604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...
- topcoder srm 575 div1
problem1 link 如果$k$是先手必胜那么$f(k)=1$否则$f(k)=0$ 通过对前面小的数字的计算可以发现:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其 ...
随机推荐
- 在caffe中执行脚本文件时 报错:-bash: ./train.sh: Permission denied
报错原因:没有权限 解决方法:chmod 777 train.sh获得权限
- orm查询语法参考文章
1.参考博客 http://blog.csdn.net/OyangYujun/article/details/45938905 ORMLite完全解析(三)官方文档第三章.自定义查询构造器 Custo ...
- <3>lua字符串
1.字符串 <1>字符串相连/加法 .. local str = "abc" str = str .. 7 --字符串与数字相连 print(str) --abc7 ...
- asp.net GridView增加删除功能
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e) { string id ...
- html5-样式表的使用-初步
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- C# WPF Halcon HDevEngine混合编程
1. WPF+Halcon 引用halcondotnet.dll和hdevenginedotnet.dll XAML中导入命名空间xmlns:halcon=”clr-namespace:HalconD ...
- 准备mysql-connector-java
下载mysql-connector-java:https://mvnrepository.com/artifact/mysql/mysql-connector-java 导入mysql-connect ...
- wingide 远程调试
1.首先你应该在本地安装wingide 6.1版本 2.大多数电脑.py文件都不能以wingide的形式打开(异常苦逼),无论是从“属性”或者是“设置”里面都不可以,无奈之下只能通过修改注册表的方式进 ...
- 实现Winform 跨线程安全访问UI控件
在多线程操作WinForm窗体上的控件时,出现“线程间操作无效:从不是创建控件XXXX的线程访问它”,那是因为默认情况下,在Windows应用程序中,.NET Framework不允许在一个线程中直接 ...
- xml.dom——文档对象模型API
文档对象模型,或者“DOM”,是一个跨语言API的World Wide Web Consortium(W3C)来访问和修改XML文档.DOM的实现提供了一个XML文档树结构,或允许客户机代码从头开始建 ...