尺取法
POJ 2566: Bound Found
题解链接 https://www.cnblogs.com/smilesundream/p/5129758.html
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
题解链接 https://www.cnblogs.com/smilesundream/p/5129758.html
*/
#include
#include
#include
#include
#include
#include
POJ 2739: Sum of Consecutive Prime Numbers
题意;输入一个数字(<=1e5)求该数可由几种在素数表中连续的素数之和组成。
欧拉筛出所有素数,因为素数序列具有单调性,所以可以用尺取法。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
题意;输入一个数字(<=1e5)求该数可由几种在素数表中连续的素数之和组成。
欧拉筛出所有素数,因为素数序列具有单调性,所以可以用尺取法。
*/
#include
#include
#include
#include
#include
#include
POJ 2100: Graveyard Design
正常尺取法即可。
后来看了题解,发现可以直接利用解方程。
三次方程求根公式很难,所以直接对n开三次方估算范围后验证。
PS:method_1结果为MLE,因为不能预处理前缀和。
同时使用vector会RE,原因未知。
method_2的结果为AC。
代码如下
/*
正常尺取法即可。
后来看了题解,发现可以直接利用1^2+2^2+...+k^2=k(k+1)(2k+1)/6=n解方程。
三次方程求根公式很难,所以直接对n开三次方估算范围后验证。
*/
#define method_2
#ifdef method_1
/*
MLE 数据量较大 不能预处理前缀和。
同时使用vector会RE,原因未知。
*/
#include
#include
#include
#include
#include
#include
反转
POJ 3185: The Water Bowls
一维的开关问题,枚举最左边的碗是否反转。后面所有的反转顺序就确定了。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
一维的开关问题,枚举最左边的碗是否反转。后面所有的反转顺序就确定了。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=20+5;
const int INF=0x3f3f3f3f;
int n=20,a[maxn],ans1=0,ans2=0,b[maxn];
void flip(int x,int a[]){
for(int i=x-1;i<=x+1;i++) a[i]=!a[i];
}
int main() {
ios::sync_with_stdio(false);
//freopen("The Water Bowls.in","r",stdin);
for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
for(int i=2;i<=n;i++){
if(a[i-1]){
flip(i,a);ans1++;
}
}
flip(1,b);ans2++;
for(int i=2;i<=n;i++){
if(b[i-1]){
flip(i,b);ans2++;
}
}
for(int i=1;i<=n;i++){
if(a[i]) ans1=INF;
if(b[i]) ans2=INF;
}
cout<
POJ 1222: EXTENDED LIGHTS OUT
经典的熄灯问题。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
经典的熄灯问题。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=5+5;
const int INF=0x3f3f3f3f;
const int dx[]= {-1,1,0,0,0};
const int dy[]= {0,0,1,-1,0};
int n,b[maxn][maxn],kase=0,c[maxn][maxn],ans1,res[maxn][maxn]= {0};
bool check(int x,int y) {
if(x<0||x>4||y<0||y>5) return false;
return true;
}
void click(int x,int y) {
for(int i=0; i<=4; i++) {
int newx=x+dx[i];
int newy=y+dy[i];
if(check(newx,newy)) {
b[newx][newy]^=1;
}
}
}
void solve() {
int ans=INF;
for(int i=0; i<=(1<<6)-1; i++) {
int cnt=0;
for(int j=0; j<=5; j++) {
if(i&(1<>n;
while(n--) {
init();
cout<<"PUZZLE #"<<++kase<>b[i][j];
b[i][j]=!b[i][j];
c[i][j]=b[i][j];
}
}
solve();
show();
}
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
弹性碰撞
POJ 2674: Linear world
第一问的解法和ant类似。
第二问需要用到一个性质,就是不管怎么碰撞,都会相对顺序都不变,而且开始有几个正向的,最后就会有几个正向的。
PS:如果将存储方式改为[1,n]就会WA,目前原因未知。
代码如下
/*
第一问的解法和ant类似。
第二问需要用到一个性质,就是不管怎么碰撞,都会相对顺序都不变,而且开始有几个正向的,最后就会有几个正向的。
PS:如果将存储方式改为[1,n]就会WA,目前原因未知。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=32000+5;
const int INF=0x3f3f3f3f;
struct node {
char p;
string name;
double pos;
} a[maxn];
double l,v;
int n;
double ans;
int ansp;
void init() {
ans=-1;
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Linear world.in","r",stdin);
while(cin>>n) {
if(!n) break;
cin>>l>>v;
init();
for(int i=0; i>a[i].p>>a[i].pos>>a[i].name; //pos自动按照升序排序 所以不用再排序
for(int i=0; ians) {
ans=dis;
ansp=i;
}
}
//实现13位的保留两位小数
printf("%13.2lf ",(int)(ans/v*100)/100.0);
int sum=0;
// D(a[ansp].name);E;
if(a[ansp].p=='p'||a[ansp].p=='P') {
for(int i=ansp+1; i
折半枚举
POJ 3977: Subset
折半搜索即可。
PS:poj不支持long long的abs,要手动实现。
代码如下
/*
折半搜索即可。
PS:poj不支持long long的abs,要手动实现。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=35+2;
const ll INF=0x3f3f3f3f3f3f3f3fll;
int n,cnt1,cnt2;
ll a[maxn],ans,ans1;
pii b[(1<=0?x:-x;
}
bool operator<(const pii i,const pii j){
//注意这里为了配合后面的lower_bound,对于first相同的pair,按照second降序排序,
//这样就能够在pos(pos=lower_bound返回值-数组首指针)的左右找到最小的子集
return i.first==j.first?i.second>j.second:i.first>n){
if(!n) break;
// int d[]={0,1,2,2,4};
// D(lower_bound(d+1,d+5,3)-d);D(upper_bound(d+1,d+5,3)-d);E;
init();
for(int i=1;i<=n;i++) cin>>a[i];
dfs1(1,0,0);
sort(b+1,b+cnt1+1);
/*
for(int i=1;i<=cnt1;i++){
D(b[i].first);D(b[i].second);
E;
}
*/
for(int i=1;i<=cnt1;i++){ //元素只来自前一半
if(ll_abs(b[i].first)
POJ 2549: Sumsets
枚举b+c和d-a,然后用二分查找判断。
时限很紧,method_1和method_2都TLE,只有method_3是500msAC。
代码如下
/*
*/
#define method_3
#ifdef method_1
/*
n^3暴力超时
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=1000+5;
const int INF=0x3f3f3f3f;
int d,num[maxn],n;
mapmp;
void init(){
mp.clear();
}
int main() {
ios::sync_with_stdio(false);
//freopen("Sumsets.in","r",stdin);
while(cin>>n){
if(!n) break;
init();
for(int i=1;i<=n;i++) cin>>num[i],mp[num[i]]=1;
sort(num+1,num+n+1);
int flag=0;
for(d=n;d>=1;d--){
if(flag) break;
for(int i=1;i<=d;i++){
if(flag) break;
for(int j=i+1;j<=d;j++){
int k=num[d]-num[i]-num[j];
if(k==num[i]||k==num[j]) continue;
if(mp[k]==1){
cout<
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=1000+5;
const int INF=0x3f3f3f3f;
int d,num[maxn],n;
map >mp; //注意这个map的对应形式
void init(){
mp.clear();
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Sumsets.in","r",stdin);
while(cin>>n){
if(!n) break;
init();
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
sort(num+1,num+n+1);
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) mp[num[i]+num[j]].push_back(make_pair(num[i],num[j])); //枚举b+c
int flag=0;
for(d=n;d>=1;d--){
if(flag) break;
for(int i=1;i<=n;i++){ //枚举a 注意可能存在负数 所以num[d]不一定大于等于num[i] 所以枚举范围不是[1,d)
if(i==d) continue;
if(flag) break;
int now=num[d]-num[i];
for(int k=0;k
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=1000+5;
const int INF=0x3f3f3f3f;
int num[maxn],n,tot1,tot2,ans;
struct node{
int v,l,r;
bool operator<(const node& h)const{return v>n){
if(!n) break;
init();
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){
a[++tot1].v=num[i]+num[j];a[tot1].l=i;a[tot1].r=j;
}
sort(a+1,a+tot1+1);
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){
b[++tot2].v=num[i]-num[j];b[tot2].l=i;b[tot2].r=j;
b[++tot2].v=num[j]-num[i];b[tot2].l=j;b[tot2].r=i;
}
for(int i=1;i<=tot2;i++){
int d=lower_bound(a+1,a+tot1+1,b[i])-a;
if(b[i].v==a[d].v&&check(b[i],a[d])){
ans=max(ans,a[d].v+num[b[i].r]);
}
}
if(ans==-INF) cout<<"no solution"<