@ivorysi
2018-01-02T08:46:27.000000Z
字数 43681
阅读 789
笔记
Inhabitants of the Wonderland have decided to hold a regional programming contest. The Judging Committee has volunteered and has promised to organize the most honest contest ever. It was decided to connect computers for the contestants using a "star" topology - i.e. connect them all to a single central hub. To organize a truly honest contest, the Head of the Judging Committee has decreed to place all contestants evenly around the hub on an equal distance from it.
To buy network cables, the Judging Committee has contacted a local network solutions provider with a request to sell for them a specified number of cables with equal lengths. The Judging Committee wants the cables to be as long as possible to sit contestants as far from each other as possible.
The Cable Master of the company was assigned to the task. He knows the length of each cable in the stock up to a centimeter,and he can cut them with a centimeter precision being told the length of the pieces he must cut. However, this time, the length is not known and the Cable Master is completely puzzled.
You are to help the Cable Master, by writing a program that will determine the maximal possible length of a cable piece that can be cut from the cables in the stock, to get the specified number of pieces.
The first line of the input file contains two integer numb ers N and K, separated by a space. N (1 = N = 10000) is the number of cables in the stock, and K (1 = K = 10000) is the number of requested pieces. The first line is followed by N lines with one number per line, that specify the length of each cable in the stock in meters. All cables are at least 1 meter and at most 100 kilometers in length. All lengths in the input file are written with a centimeter precision, with exactly two digits after a decimal point.
Write to the output file the maximal length (in meters) of the pieces that Cable Master may cut from the cables in the stock to get the requested number of pieces. The number must be written with a centimeter precision, with exactly two digits after a decimal point.
If it is not possible to cut the requested number of pieces each one being at least one centimeter long, then the output file must contain the single number "0.00" (without quotes).
4 11
8.02
7.43
4.57
5.39
2.00
很明显的二分,然而精度卡的很恶心,只能转换成longlong来做……
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define esp 1e-8
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
double c[20005];
ll cable[20005];
ll sum=0,k;
bool check(ll mid) {
ll cnt=0;
siji(i,1,n) {
cnt+=cable[i]/mid;
if(cnt>=k) return true;
}
return false;
}
void solve() {
scanf("%d%lld",&n,&k);
siji(i,1,n) {
scanf("%lf",&c[i]);
cable[i]=(c[i]+0.005)*100;
sum+=cable[i];
}
if(k>sum) {puts("0.00");return;}
ll l=0,r=sum;
while(l<r) {
ll mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%.2f\n",(double)l/100.0);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤ moneyi ≤ 10,000) that he will need to spend each day over the next N (1 ≤ N ≤ 100,000) days.
FJ wants to create a budget for a sequential set of exactly M (1 ≤ M ≤ N) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.
FJ's goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.
Line 1: Two space-separated integers: N and M
Lines 2..N+1: Line i+1 contains the number of dollars Farmer John spends on the ith day
Line 1: The smallest possible monthly limit Farmer John can afford to live with.
7 5
100
400
300
100
500
101
400
500
下边界是最大花钱的那天的钱数,上边界是所有钱的总和,然后二分
每次O(N)判断是否合法
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define esp 1e-8
//#define ivorysi
using namespace std;
typedef long long ll;
int n,m;
ll budget[1000005];
bool check(ll mid) {
int cnt=0;
ll all=budget[1];
siji(i,2,n) {
if(all+budget[i]>mid) {
++cnt;
all=budget[i];
}
else {
all+=budget[i];
}
}
++cnt;
return cnt<=m;
}
void solve() {
scanf("%d%d",&n,&m);
ll l=0,r=0;
siji(i,1,n) {
scanf("%lld",&budget[i]);
r+=budget[i];
l=max(l,budget[i]);
}
while(l<r) {
ll mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%lld\n",r);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
The determinant of a matrix 2 × 2 is defined as follows:
A matrix is called degenerate if its determinant is equal to zero.
The norm ||A|| of a matrix A is defined as a maximum of absolute values of its elements.
You are given a matrix . Consider any degenerate matrix B such that norm ||A - B|| is minimum possible. Determine ||A - B||.
The first line contains two integers a and b (|a|, |b| ≤ 109), the elements of the first row of matrix A.
The second line contains two integers c and d (|c|, |d| ≤ 109) the elements of the second row of matrix A.
Output a single real number, the minimum possible value of ||A - B||. Your answer is considered to be correct if its absolute or relative error does not exceed 10 - 9.
1 2
3 4
0.2000000000
1 0
0 1
0.5000000000
这道题本来想看题解
但是题解加载不出来,然后就自己想出来了
因为精度又被卡了,但是在网上学到一个小技巧,对于浮点数的二分直接确定枚举次数,例如1000000次,就很秒了
我们观察一下我们枚举一个绝对值k
ad的取值是一个区间,bc的取值是一个区间
我们区间求交,如果有交的话那么k一定是合法的,然后r=k 否则l=k
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define esp 1e-6
//#define ivorysi
using namespace std;
typedef long long ll;
double a,b,c,d;
double tmp[8];
void make_data(double p,double q,double k) {
tmp[1]=(p+k)*(q+k);
tmp[2]=(p+k)*(q-k);
tmp[3]=(p-k)*(q+k);
tmp[4]=(p-k)*(q-k);
}
bool check(double mid) {
make_data(a,d,mid);
double r1=tmp[1],l1=tmp[1];
siji(i,2,4) {
r1=max(r1,tmp[i]);
l1=min(l1,tmp[i]);
}
make_data(b,c,mid);
double r2=tmp[1],l2=tmp[1];
siji(i,2,4) {
r2=max(r2,tmp[i]);
l2=min(l2,tmp[i]);
}
if(l1<r2 && l2<r1) return true;
else return false;
}
void solve() {
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
double l=0.0,r=1000000000.0;
int num=1000000;
while(num--) {
double mid=(l+r)/2.0;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.9lf\n",r);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间
输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By 第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy 第三行是3个整数,分别是P,Q,R
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位
0 0 0 100
100 0 100 100
2 2 1
136.60
对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10
我们用光的折射原理,AB上任意一点到D一定有一个极小值
然后我们将平面和D作为同一种介质,我们可以也以为AB上到D的距离也一定有一个极小值
三分套三分
要在必要的时候用sqrt否则会被卡精度啊!!!!
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define esp 1e-8
//#define ivorysi
using namespace std;
typedef long long ll;
struct Point {
double x,y;
Point() {}
Point(double _x,double _y) {
x=_x;y=_y;
}
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x+b.x,a.y+b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x-b.x,a.y-b.y);
}
friend double operator * (const Point &a,const Point &b) {
return a.x*b.y-a.y*b.x;
}
friend Point operator * (const Point &a,const double &b) {
return Point(a.x*b,a.y*b);
}
friend Point operator / (const Point &a,const double &b) {
return Point(a.x/b,a.y/b);
}
double norm() {
return sqrt(x*x+y*y);
}
}A,B,C,D;
double p,q,r;
double dist(Point Z,Point L) {
return (L-D).norm()/q+(L-Z).norm()/r;
}
double calc(Point mid) {
Point ll=D,rr=C;
int num=500;
while(num--) {
Point m1=ll+(rr-ll)/3.0;
Point m2=rr-(rr-ll)/3.0;
if(dist(mid,m1)-dist(mid,m2)>= -esp) ll=m1;
else rr=m2;
}
return dist(mid,rr)+(mid-A).norm()/p;
}
void solve() {
scanf("%lf%lf",&A.x,&A.y);
scanf("%lf%lf",&B.x,&B.y);
scanf("%lf%lf",&C.x,&C.y);
scanf("%lf%lf",&D.x,&D.y);
scanf("%lf%lf%lf",&p,&q,&r);
Point ll=A,rr=B;
int num=500;
while(num--) {
Point m1=ll+(rr-ll)/3.0;
Point m2=rr-(rr-ll)/3.0;
if(calc(m1)-calc(m2)>= esp) ll=m1;
else rr=m2;
}
printf("%.2lf\n",calc(ll));
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
You are given a sequence of n integers a1, a2, ..., an.
Determine a real number x such that the weakness of the sequence a1 - x, a2 - x, ..., an - x is as small as possible.
The weakness of a sequence is defined as the maximum value of the poorness over all segments (contiguous subsequences) of a sequence.
The poorness of a segment is defined as the absolute value of sum of the elements of segment.
The first line contains one integer n (1 ≤ n ≤ 200 000), the length of a sequence.
The second line contains n integers a1, a2, ..., an (|ai| ≤ 10 000).
Output a real number denoting the minimum possible weakness of a1 - x, a2 - x, ..., an - x. Your answer will be considered correct if its relative or absolute error doesn't exceed 10 - 6.
3
1 2 3
1.000000000000000
4
1 2 3 4
2.000000000000000
10
1 10 2 9 3 8 4 7 5 6
4.500000000000000
For the first case, the optimal value of x is 2 so the sequence becomes - 1, 0, 1 and the max poorness occurs at the segment "-1" or segment "1". The poorness value (answer) equals to 1 in this case.
For the second sample the optimal value of x is 2.5 so the sequence becomes - 1.5, - 0.5, 0.5, 1.5 and the max poorness occurs on segment "-1.5 -0.5" or "0.5 1.5". The poorness value (answer) equals to 2 in this case.
这道题我们可以认为每个区间的值都是一个绝对值函数,这些函数复合起来求最大值是一个单峰函数,或者说是单谷函数
然后我们可以三分
如何求函数值呢,我们处理出一个前缀和,一个区间和是sum[r]-sum[l],我们固定一个r,然后找sum[l]的最大值和最小值,对每个函数值取一个max就是这个地方的函数值
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define esp 1e-8
#define MAXN 2000005
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
double a[MAXN];
double tmp[MAXN];
double calc(double mid) {
siji(i,1,n) tmp[i]=a[i]-mid;
tmp[0]=0;
siji(i,1,n) tmp[i]+=tmp[i-1];
double mi=min(0.0,tmp[1]),ma=max(0.0,tmp[1]);
double ans=fabs(tmp[1]);
siji(i,2,n) {
ans=max(ans,fabs(tmp[i]-mi));
ans=max(ans,fabs(tmp[i]-ma));
mi=min(mi,tmp[i]);
ma=max(ma,tmp[i]);
}
return ans;
}
void solve() {
scanf("%d",&n);
double l=100000.0,r=0;
siji(i,1,n) {
scanf("%lf",&a[i]);
r=max(a[i],r);
l=min(a[i],l);
}
int num=200;
while(num--) {
double m1=l+(r-l)/3.0;
double m2=r-(r-l)/3.0;
if(calc(m1)>=calc(m2)) l=m1;
else r=m2;
}
printf("%.9lf\n",calc(l));
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
The starry sky in the summer night is one of the most beautiful things on this planet. People imagine that some groups of stars in the sky form so-called constellations. Formally a constellation is a group of stars that are connected together to form a figure or picture. Some well-known constellations contain striking and familiar patterns of bright stars. Examples are Orion (containing a figure of a hunter), Leo (containing bright stars outlining the form of a lion), Scorpius (a scorpion), and Crux (a cross).
In this problem, you are to find occurrences of given constellations in a starry sky. For the sake of simplicity, the starry sky is given as a N × M matrix, each cell of which is a '*' or '0' indicating a star in the corresponding position or no star, respectively. Several constellations are given as a group of T P × Q matrices. You are to report how many constellations appear in the starry sky.
Note that a constellation appears in the sky if and only the corresponding P × Q matrix exactly matches some P × Q sub-matrix in the N × M matrix.
The input consists of multiple test cases. Each test case starts with a line containing five integers N, M, T, P and Q(1 ≤ N, M ≤ 1000, 1 ≤ T ≤ 100, 1 ≤ P, Q ≤ 50).
The following N lines describe the N × M matrix, each of which contains M characters '*' or '0'.
The last part of the test case describe T constellations, each of which takes P lines in the same format as the matrix describing the sky. There is a blank line preceding each constellation.
The last test case is followed by a line containing five zeros.
For each test case, print a line containing the test case number( beginning with 1) followed by the number of constellations appearing in the sky.
3 3 2 2 2
00
0*
*00**
000
*
3 3 2 2 2
00
0*
*00**
000
0
0 0 0 0 0
Case 1: 1
Case 2: 2
这道题hash没有暴力跑得快
把每一行的q个都给二进制,然后子方格二进制压起来,然后一行行暴力匹配
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
//#define ivorysi
using namespace std;
typedef long long ll;
int n,m,t,p,q;
char map[1005][1005];
ll hash[1005][1005],h[105];
int ans;
bool check() {
siji(i,1,n-p+1) {
siji(j,1,m-q+1) {
if(hash[i][j]==h[1]) {
siji(k,2,p) {
if(hash[i+k-1][j]!=h[k]) goto fail;
}
return true;
}
fail:;
}
}
return false;
}
void solve() {
if(n<p || m<q) {puts("0");return;}
memset(hash,0,sizeof(hash));
siji(i,1,n) {
scanf("%s",map[i]+1);
siji(k,1,q) {
if(map[i][k]=='*') {
hash[i][1]|=((ll)1<<(k-1));
}
}
siji(j,2,m-q+1) {
hash[i][j]=hash[i][j-1]>>1;
if(map[i][j+q-1]=='*') {
hash[i][j]|=((ll)1<<(q-1));
}
}
}
ans=0;
while(t--) {
memset(h,0,sizeof(h));
siji(i,1,p) {
scanf("%s",map[i]+1);
siji(j,1,q) {
if(map[i][j]=='*') {
h[i]|=((ll)1<<(j-1));
}
}
}
if(check()) ++ans;
}
printf("%d\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int c=0;
while(scanf("%d%d%d%d%d",&n,&m,&t,&p,&q)!=EOF) {
if(n==0 && m==0 && t==0 && p==0 && q==0) break;
++c;
printf("Case %d: ",c);
solve();
}
return 0;
}
机房这个神奇的地方总是存在这一些神奇的字符串
就拿lzlj来说吧,就有着许多意思
泸州老窖
龙章麟角
老子垃圾
连战连捷
当然还有**垃圾
然而机房里某位具有毒奶的人却不愿听到lzlj,而胡小兔和其他一群菜鸡总喜欢讲话.
所以她现在交给你一个任务,让你判断讲话内容中什么时候出现了她不喜欢的词汇
(如果你不想完成这个任务的话,请你输出lzlj,并准备接受毒奶)
第一行一个正整数n(1<=n<=1000),表示她一共有n个不想听到的词汇
接下来第2到n+1行,每行一个字符串S[i]表示该词汇(|S|<=20)
第n+2行一个正整数m(m<=1000000),表示机房讲话内容的长度
第n+3行一个长度为m的字符串T
一个长度为m的数字串,第i位输出1表示存在以T[i]开头的不喜欢的词汇,0则为不存在
1
lzlj
50
lzljlinzhihaoalzllzljllzjjlzljpleasedontmilkmelzlj
10000000000000000100000000100000000000000000001000
这个题出的
好啊!
因为hash不擅长比较长度不相同的字符串,所以我们按照长度进行插入,每次清空一遍哈希表,然后检查这个位置的串是不是合法,我们可以用单变量从后往前扫来得到m串固定长度的哈希值
这道题由于太随机了,一个普通的模数会被卡死,所以我们要写双哈希
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
//#define ivorysi
using namespace std;
typedef long long ll;
int n,m;
char s[1005][55];
char str[1000005];
vector<int> v[55];
bool lz[1000005];
ll e[2][25];
ll ha[2]={99994711,1274436047};
int ba[2]={823,757};
struct node {
ll val;
int next;
}edge[2][2000005];
int head[2][MOD+5],sumedge[2];
void add(int id,int u,ll x) {
edge[id][++sumedge[id]].val=x;
edge[id][sumedge[id]].next=head[id][u];
head[id][u]=sumedge[id];
}
void ins(int id,ll x) {
x%=ha[id];
int u=(int)x%MOD;
for(int i=head[id][u];i;i=edge[id][i].next) {
if(edge[id][i].val==x) return ;
}
add(id,u,x);
}
bool find(int id,ll x) {
x%=ha[id];
int u=(int)x%MOD;
for(int i=head[id][u];i;i=edge[id][i].next) {
if(edge[id][i].val==x) return true;
}
return false;
}
ll calc(int pos,int id) {
int l=strlen(s[id]+1);
ll res=0;
siji(i,1,l) {
res+=e[pos][i-1]*(s[id][i]-'a'+1)%ha[pos];
res%=ha[pos];
}
return res;
}
ll change(int id,ll x,int pos,int k) {
x-=(str[pos]-'a'+1)*e[id][k-1]%ha[id];
x=(x%ha[id]+ha[id])%ha[id];
x=x*e[id][1]%ha[id];
x+=(str[pos-k]-'a'+1);
x%=ha[id];
return x;//忘记return 了, gg
}
void solve() {
e[0][0]=1;e[1][0]=1;
siji(i,1,20) {
e[0][i]=e[0][i-1]*ba[0]%ha[0];
e[1][i]=e[1][i-1]*ba[1]%ha[1];
}
scanf("%d",&n);
siji(i,1,n) {
scanf("%s",s[i]+1);
v[strlen(s[i]+1)].push_back(i);
}
scanf("%d",&m);
scanf("%s",str+1);
siji(j,1,20) {
if(m<j) break;
memset(head,0,sizeof(head));
memset(sumedge,0,sizeof(sumedge));
int si=v[j].size();
if(si==0) continue;
xiaosiji(k,0,si) {
ins(0,calc(0,v[j][k]));
ins(1,calc(1,v[j][k]));
}
ll now0=0,now1=0;
int t=0;
siji(i,m-j+1,m) {
now0+=(str[i]-'a'+1)*e[0][t]%ha[0];
now1+=(str[i]-'a'+1)*e[1][t]%ha[1];
++t;
now0%=ha[0];
now1%=ha[1];
}
gongzi(i,m,j) {
if(find(0,now0)&&find(1,now1)) {
lz[i-j+1]=1;
}
now0=change(0,now0,i,j);
now1=change(1,now1,i,j);
}
}
siji(i,1,m) {
if(lz[i]) printf("1");
else printf("0");
}
puts("");
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
Sometimes it is hard to prepare tests for programming problems. Now Bob is preparing tests to new problem about strings — input data to his problem is one string. Bob has 3 wrong solutions to this problem. The first gives the wrong answer if the input data contains the substring s1, the second enters an infinite loop if the input data contains the substring s2, and the third requires too much memory if the input data contains the substring s3. Bob wants these solutions to fail single test. What is the minimal length of test, which couldn't be passed by all three Bob's solutions?
There are exactly 3 lines in the input data. The i-th line contains string si. All the strings are non-empty, consists of lowercase Latin letters, the length of each string doesn't exceed 105.
Output one number — what is minimal length of the string, containing s1, s2 and s3 as substrings.
ab
bc
cd
4
abacaba
abaaba
x
11
这道题我们用hash暴力就好
我们先忽略所有串是另一个串子串
然后前后链接这么匹配,找前后链接的最大长度用暴力去找
然后生成一个新的串,求新的hash,然后再和下一个进行匹配
有特殊情况是一个串包含了剩下所有的串
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
//#define ivorysi
using namespace std;
typedef long long ll;
char s[10][300005];
ll e[300010];
ll h[10][300005];
int now[10],cnt,ans;
bool used[10];
bool check(int a,int l1,int r1,int b ,int l2,int r2) {
ll res=e[200000-l1]*(h[a][r1]-h[a][l1-1])%ha-e[200000-l2]*(h[b][r2]-h[b][l2-1])%ha;
res=(res%ha+ha)%ha;
return res==0;
}
void calc() {
int len=0;
siji(i,2,cnt) {
int la=strlen(s[now[i-1]]+1),lb=strlen(s[now[i]]+1);
int l=min(la,lb);
for(len=l;len>=1;--len) {
if(check(now[i-1],la-len+1,la,now[i],1,len)) break;
}
siji(j,1,la-len) {
s[4][j]=s[now[i-1]][j];
}
siji(j,1,lb) {
s[4][j+la-len]=s[now[i]][j];
}
s[4][lb+la-len+1]='\0';
now[i]=4;
siji(j,1,lb+la-len) {
h[4][j]=h[4][j-1]+e[j-1]*(s[4][j]-'a'+1)%ha;
h[4][j]%=ha;
}
}
ans=min(ans,(int)strlen(s[4]+1));
ans=max(ans,(int)strlen(s[now[1]]+1));
}
void dfs(int dep) {
if(dep>cnt) {
calc();
return;
}
siji(i,0,2) {
if(used[i]) {
used[i]=0;
now[dep]=i;
dfs(dep+1);
used[i]=1;
}
}
}
void solve() {
e[0]=1;
siji(i,1,200000) {
e[i]=e[i-1]*ba%ha;
}
scanf("%s%s%s",s[0]+1,s[1]+1,s[2]+1);
ans=strlen(s[0]+1)+strlen(s[1]+1)+strlen(s[2]+1);
if(strlen(s[0]+1)<strlen(s[1]+1)) swap(s[0],s[1]);
if(strlen(s[0]+1)<strlen(s[2]+1)) swap(s[0],s[2]);
if(strlen(s[1]+1)<strlen(s[2]+1)) swap(s[1],s[2]);
siji(i,0,2) {
int len=strlen(s[i]+1);
siji(j,1,len) {
h[i][j]=h[i][j-1]+e[j-1]*(s[i][j]-'a'+1)%ha;
h[i][j]%=ha;
}
}
memset(used,1,sizeof(used));
siji(i,1,2) {
siji(j,0,i-1) {
if(!used[j]) continue;
int l=strlen(s[j]+1),z=strlen(s[i]+1);
siji(k,1,l-z+1) {
if(check(j,k,k+z-1,i,1,z)) {used[i]=0;break;}
}
if(!used[i]) break;
}
}
siji(i,0,2) if(used[i]) ++cnt;
dfs(1);
printf("%d\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
return 0;
}
二分图有一些很秒的公式啊
|最大匹配数|=|最小顶点覆盖|
最小顶点覆盖的意思是我们选择个数最少的点然后覆盖所有的边
我们考虑每一条边一定连着一个被匹配的点,如果一条边连着一个未匹配的点,那么这条边也一定连着一条被匹配的点,否则匹配可以增加
|最大独立集|+|最小顶点覆盖|=顶点个数
最大独立集就是选出一些点,这些点之间没有边相连
我们把最小顶点覆盖去除了,那么剩下的顶点就没有边了啊
|最大匹配|+|最小边覆盖|=顶点个数
我们往最大匹配中加边,就可以覆盖所有顶点了,所以这个式子告诉我们,最小边覆盖就是选择最大匹配的那些边,然后加入新的边将未匹配点链接起来
Mike is the owner of a cheese factory. He has 2N cheeses and each cheese is given a binary number from 00...0 to 11...1. To keep his cheese free from viruses, he made himself a purifying machine to clean virus-infected cheese. As a talented programmer, his purifying machine is built in a special way. His purifying machine has N switches, each switch has three states, 1, 0 and *. An operation of this machine is a cleaning action according to the states of the N switches. During one operation, at most one switch can be turned to state *, which can substitute for either 1 or 0. When the machine is turned to a specific state, an operation will clean all the cheeses with corresponding binary numbers. For example, if N equals 6 and the switches are turned to 01*100, the cheeses numbered 010100 and 011100 are under operation by the machine.
One day, Mike's machine was infected. When Mike found out, he had already done some operations and the cheeses operated by this infected machine were infected too. He cleaned his machine as quickly as he could, and now he needs to clean the infected cheeses with the minimum number of operations. If a cheese is infected, cleaning this cheese with the machine one or more times will make this cheese free from virus again; but if a cheese is not infected, operation on this cheese will make it go bad.
Now given the infected operations Mike has done, you need to find out the minimum number of operations that must be performed to clean all the infected cheeses without making any clean cheese go bad.
There are several test cases. Each test case starts with a line containing two numbers N and M (1 <= N <= 10, 1 <= M <= 1000). N is the number of switches in the machine and M is the number of infected operations Mike has done. Each of the following M lines contains a switch state of the machine. A test case with N = M = 0 ends the input and should not be processed.
For each test case, output one line containing an integer, which is the minimum number of operations Mike needs to do.
3 3
*01
100
011
0 0
2
这道题“at most one switch can be turned to state *”
╮(╯▽╰)╭思考的方向一开始就跑偏了,以为会有很多*其实只有一个
只有一个的话就很好考虑了,我们创造出所有被污染的奶酪编号,然后我们在每两个二进制位只相差一位的奶酪编号连上一条边,然后跑二分图匹配
这道题要求的是最小边覆盖,运用公式|最大匹配数|+|最小边覆盖|=|V|
这道题的from一定需要是-1因为0也是一个点
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
//#define ivorysi
using namespace std;
typedef long long ll;
int n,m;
char s[105];
vector<int> g[2200];
bool used[2200],vis[2200];
int num[3500],now=0,tot,par[3500],ans;
void dfs(int dep) {
if(dep>n) {
if(!used[now]) {
used[now]=1;
num[++tot]=now;
}
return;
}
if(s[dep]=='*') {
now=(now<<1)|1;
dfs(dep+1);
now>>=1;
now=(now<<1);
dfs(dep+1);
}
if(s[dep]=='1') {
now=(now<<1)|1;
dfs(dep+1);
now>>=1;
}
if(s[dep]=='0') {
now=(now<<1);
dfs(dep+1);
now>>=1;
}
}
int lowbit(int x) {
return x&(-x);
}
bool match(int u) {
int s=g[u].size();
xiaosiji(i,0,s) {
int v=g[u][i];
if(!vis[v]) {
vis[v]=1;
if(par[v]==-1 || match(par[v])) {
par[v]=u;
par[u]=v;
return true;
}
}
}
return false;
}
void solve() {
siji(i,0,1024) g[i].clear();
memset(num,0,sizeof(num));
memset(used,0,sizeof(used));
memset(par,-1,sizeof(par));
tot=0;
ans=0;
siji(i,1,m) {
scanf("%s",s+1);
now=0;
dfs(1);
}
siji(i,1,tot) {
siji(j,i+1,tot) {
int C=num[i]^num[j];
if(C-lowbit(C)==0) {
g[num[i]].push_back(num[j]);
g[num[j]].push_back(num[i]);
}
}
}
siji(i,0,1024) {
if(used[i]) {
if(par[i]==-1) {
memset(vis,0,sizeof(vis));
if(match(i)) ++ans;
}
}
}
printf("%d\n",tot-ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
while(scanf("%d%d",&n,&m)!=EOF){
if(n+m==0) break;
solve();
}
return 0;
}
Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an intersection and walking through town's streets you can never reach the same intersection i.e. the town's streets form no cycles.
With these assumptions your task is to write a program that finds the minimum number of paratroopers that can descend on the town and visit all the intersections of this town in such a way that more than one paratrooper visits no intersection. Each paratrooper lands at an intersection and can visit other intersections following the town streets. There are no restrictions about the starting intersection for each paratrooper.
Your program should read sets of data. The first line of the input file contains the number of the data sets. Each data set specifies the structure of a town and has the format:
no_of_intersections
no_of_streets
S1 E1
S2 E2
......
Sno_of_streets Eno_of_streets
The first line of each data set contains a positive integer no_of_intersections (greater than 0 and less or equal to 120), which is the number of intersections in the town. The second line contains a positive integer no_of_streets, which is the number of streets in the town. The next no_of_streets lines, one for each street in the town, are randomly ordered and represent the town's streets. The line corresponding to street k (k <= no_of_streets) consists of two positive integers, separated by one blank: Sk (1 <= Sk <= no_of_intersections) - the number of the intersection that is the start of the street, and Ek (1 <= Ek <= no_of_intersections) - the number of the intersection that is the end of the street. Intersections are represented by integers from 1 to no_of_intersections.
There are no blank lines between consecutive sets of data. Input data are correct.
The result of the program is on standard output. For each input data set the program prints on a single line, starting from the beginning of the line, one integer: the minimum number of paratroopers required to visit all the intersections in the town.
2
4
3
3 4
1 3
2 3
3
3
1 3
1 2
2 3
2
1
这道题我们这样考虑,求一个最小路径覆盖
我们把每个点拆成两个点,然后如果u到v有一条边,然后从u到v'连一个点,求最大匹配
n-最大匹配数就是我们的答案
为什么呢……可以这么想,我们有一条路径a->b b->c c->d
我们一定匹配了三条边a->b b->c c->d
经过的节点数是4个,然后需要走的点是4-3=1个
最后呢,其实在代码里不用把点拆开,我们的边都是有向边,from只要更新从谁走过来就可以了,而由于我们不能逆着边走,题里有没有环,所以我们的情况不会发生冲突
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
//#define ivorysi
using namespace std;
typedef long long ll;
int T,n,m;
struct node {
int to,next;
}edge[10005];
int head[10005],sumedge,from[10005],ans;
bool vis[10005];
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
bool match(int u) {
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!vis[v]) {
vis[v]=1;
if(from[v]==0 || match(from[v])) {
from[v]=u;
return true;
}
}
}
return false;
}
void solve() {
scanf("%d%d",&n,&m);
memset(from,0,sizeof(from));
memset(head,0,sizeof(head));
sumedge=0;
ans=0;
int u,v;
siji(i,1,m) {
scanf("%d%d",&u,&v);
add(u,v);
}
siji(i,1,n) {
memset(vis,0,sizeof(vis));
if(match(i)) ++ans;
}
printf("%d\n",n-ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d",&T);
while(T--) {
solve();
}
return 0;
}
Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he is not a very tidy person and has put all his transparencies on one big heap. Before giving the talk, he has to sort the slides. Being a kind of minimalist, he wants to do this with the minimum amount of work possible.
The situation is like this. The slides all have numbers written on them according to their order in the talk. Since the slides lie on each other and are transparent, one cannot see on which slide each number is written.
Well, one cannot see on which slide a number is written, but one may deduce which numbers are written on which slides. If we label the slides which characters A, B, C, ... as in the figure above, it is obvious that D has number 3, B has number 1, C number 2 and A number 4.
Your task, should you choose to accept it, is to write a program that automates this process.
The input consists of several heap descriptions. Each heap descriptions starts with a line containing a single integer n, the number of slides in the heap. The following n lines contain four integers xmin, xmax, ymin and ymax, each, the bounding coordinates of the slides. The slides will be labeled as A, B, C, ... in the order of the input.
This is followed by n lines containing two integers each, the x- and y-coordinates of the n numbers printed on the slides. The first coordinate pair will be for number 1, the next pair for 2, etc. No number will lie on a slide boundary.
The input is terminated by a heap description starting with n = 0, which should not be processed.
For each heap description in the input first output its number. Then print a series of all the slides whose numbers can be uniquely determined from the input. Order the pairs by their letter identifier.
If no matchings can be determined from the input, just print the word none on a line by itself.
Output a blank line after each test case.
4
6 22 10 20
4 18 6 16
8 20 2 18
10 24 4 8
9 15
19 17
11 7
21 11
2
0 2 0 2
0 2 0 2
1 1
1 1
0
Heap 1
(A,4) (B,1) (C,2) (D,3)Heap 2
none
又因为没好好读题naive了
Then print a series of all the slides whose numbers can be uniquely determined from the input
这说明了输入不是完全合法的,我们是要找哪些边一定在最大匹配里
求一个最大匹配和边集,然后删除每条边再求一次最大匹配,看看最大匹配的数目有没有减少,有减少的话就证明不是
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
#define pii pair<int,int>
#define fi first
#define se second
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
int g[105][105];
char *s="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int xmin[105],xmax[105],ymin[105],ymax[105],ql,num,from[105],ans[105],cnt;
pii que[105];
bool vis[105];
bool match(int u) {
siji(v,1,60) {
if(g[u][v]) {
if(!vis[v]) {
vis[v]=1;
if(from[v]==0 || match(from[v])) {
from[v]=u;
return true;
}
}
}
}
return false;
}
int calc(pii k) {
g[k.fi][k.se]=0;
int res=0;
memset(from,0,sizeof(from));
siji(i,1,n) {
memset(vis,0,sizeof(vis));
if(match(i)) {
++res;
}
}
g[k.fi][k.se]=1;
return res;
}
void solve() {
memset(from,0,sizeof(from));
memset(ans,0,sizeof(ans));
memset(g,0,sizeof(g));
memset(ans,0,sizeof(ans));
ql=0;
cnt=0;
num=0;
siji(i,1,n) {
scanf("%d%d%d%d",&xmin[i],&xmax[i],&ymin[i],&ymax[i]);
}
int x,y;
siji(i,1,n) {
scanf("%d%d",&x,&y);
siji(j,1,n) {
if(xmin[j]<=x && xmax[j]>=x && ymin[j]<=y && ymax[j]>=y) {
g[j][i+n]=1;
}
}
}
siji(i,1,n) {
memset(vis,0,sizeof(vis));
if(match(i)) ++num;
}
siji(i,n+1,2*n) {
que[++ql]=make_pair(from[i],i);
}
siji(i,1,ql) {
if(calc(que[i])<num) {
++cnt;
ans[que[i].fi]=que[i].se-n;
}
}
if(cnt==0) {
puts("none");
return;
}
int t=0;
siji(i,1,n) {
if(ans[i]!=0) {
++t;
printf("(%c,%d)%c",s[i-1],ans[i]," \n"[t==cnt]);
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T=0;
while(1) {
scanf("%d",&n);
if(!n) break;
++T;
if(T!=1) puts("");
printf("Heap %d\n",T);
solve();
}
return 0;
}
在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑
士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空
位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步
数完成任务。
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑
士,*表示空位。两组数据之间没有空行。
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
7
-1
我们的估价函数表示至少要走的步数,值是当前状态和目标状态不同的位置的个数-1
然后逐渐枚举深度,进行搜索
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
#define pii pair<int,int>
#define fi first
#define se second
//#define ivorysi
using namespace std;
typedef long long ll;
int T,stx,sty,dep;
char cur[5][5];
char last[5][5]={
{'1','1','1','1','1'},
{'0','1','1','1','1'},
{'0','0','*','1','1'},
{'0','0','0','0','1'},
{'0','0','0','0','0'}
};
int dx[]={1,-1,1,-1,2,-2,2,-2};
int dy[]={2,2,-2,-2,1,1,-1,-1};
int H() {
int res=-1;
siji(i,0,4) {
siji(j,0,4) {
if(last[i][j]!=cur[i][j]) ++res;
}
}
return res;
}
bool check(int x,int y) {
return x>=0 && x<=4 && y>=0 && y<=4;
}
bool dfs(int step,int x,int y) {
if(step>dep) {
if(H()==-1) return true;
return false;
}
if(step+H()-1 > dep) return false;
siji(i,0,7) {
int fx=x+dx[i],fy=y+dy[i];
if(check(fx,fy)) {
swap(cur[fx][fy],cur[x][y]);
if(dfs(step+1,fx,fy)) return true;
swap(cur[fx][fy],cur[x][y]);
}
}
return false;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d",&T);
while(T--) {
siji(i,0,4) {
scanf("%s",cur[i]);
}
siji(i,0,4) {
siji(j,0,4) {
if(cur[i][j]=='*') stx=i,sty=j;
}
}
siji(i,0,15) {
dep=i;
if(dfs(1,stx,sty)) {
printf("%d\n",dep);
goto succ;
}
}
puts("-1");
succ:;
}
return 0;
}
The rotation game uses a # shaped board, which can hold 24 pieces of square blocks (see Fig.1). The blocks are marked with symbols 1, 2 and 3, with exactly 8 pieces of each kind.
Initially, the blocks are placed on the board randomly. Your task is to move the blocks so that the eight blocks placed in the center square have the same symbol marked. There is only one type of valid move, which is to rotate one of the four lines, each consisting of seven blocks. That is, six blocks in the line are moved towards the head by one block and the head block is moved to the end of the line. The eight possible moves are marked with capital letters A to H. Figure 1 illustrates two consecutive moves, move A and move C from some initial configuration.
The input consists of no more than 30 test cases. Each test case has only one line that contains 24 numbers, which are the symbols of the blocks in the initial configuration. The rows of blocks are listed from top to bottom. For each row the blocks are listed from left to right. The numbers are separated by spaces. For example, the first test case in the sample input corresponds to the initial configuration in Fig.1. There are no blank lines between cases. There is a line containing a single `0' after the last test case that ends the input.
For each test case, you must output two lines. The first line contains all the moves needed to reach the final configuration. Each move is a letter, ranging from
A' to
H', and there should not be any spaces between the letters in the line. If no moves are needed, output `No moves needed' instead. In the second line, you must output the symbol of the blocks in the center square after these moves. If there are several possible solutions, you must output the one that uses the least number of moves. If there is still more than one possible solution, you must output the solution that is smallest in dictionary order for the letters of the moves. There is no need to output blank lines between cases.
1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
0
AC
2
DDHH
2
A*函数是还差几个数能构成中间方格的8个数
然后我这个zz
我把格子的长度打成了8
然后自己毫无知觉……wtf……为什么能过样例啊
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MOD 974711
#define ba 823
#define ha 99994711
#define pii pair<int,int>
#define fi first
#define se second
//#define ivorysi
using namespace std;
typedef long long ll;
int ori[30],dep=0;
int cur[5][10];
int op[10],line[10],d[10],ans[106];
int H() {
int cnt[4]={0,0,0,0};
siji(j,0,1) {
siji(i,2,4) {
cnt[cur[j][i]]++;
}
}
cnt[cur[2][3]]++;
cnt[cur[3][3]]++;
int res=8-cnt[1];
res=min(res,8-cnt[2]);
res=min(res,8-cnt[3]);
return res;
}
void update(int x) {
if(x==0) {
cur[2][2]=cur[0][2];
cur[3][2]=cur[0][4];
}
else if(x==1) {
cur[2][4]=cur[1][2];
cur[3][4]=cur[1][4];
}
else if(x==2) {
cur[0][2]=cur[2][2];
cur[1][2]=cur[2][4];
}
else {
cur[0][4]=cur[3][2];
cur[1][4]=cur[3][4];
}
}
void change(int id,int dir) {
int tmp[10];
memcpy(tmp,cur[id],sizeof(cur[id]));
siji(i,0,6) {
cur[id][i]=tmp[(i+dir+7)%7];
}
}
bool dfs(int step,int prev) {
if(step>dep) {
if(H()==0) return true;
else return false;
}
if(step+H()-1 > dep) return false;
siji(i,0,7) {
if(i==op[prev]) continue;
else {
change(line[i],d[i]);
update(line[i]);
ans[step]=i;
if(dfs(step+1,i)) return true;
change(line[i],-d[i]);
update(line[i]);
}
}
return false;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
op[0]=5;op[1]=4;op[2]=7;op[3]=6;
op[5]=0;op[4]=1;op[7]=2;op[6]=3;
op[8]=-1;
line[0]=line[5]=0;
line[1]=line[4]=1;
line[2]=line[7]=2;
line[3]=line[6]=3;
d[0]=d[1]=d[6]=d[7]=1;
d[2]=d[3]=d[4]=d[5]=-1;
while(1) {
scanf("%d",&ori[1]);
if(ori[1]==0) break;
siji(i,2,24) scanf("%d",&ori[i]);
siji(i,5,11) cur[2][i-5]=ori[i];
siji(i,14,20) cur[3][i-14]=ori[i];
cur[0][0]=ori[1];cur[0][1]=ori[3];
cur[0][2]=ori[7];cur[0][3]=ori[12];
cur[0][4]=ori[16];cur[0][5]=ori[21];
cur[0][6]=ori[23];
cur[1][0]=ori[2];cur[1][1]=ori[4];
cur[1][2]=ori[9];cur[1][3]=ori[13];
cur[1][4]=ori[18];cur[1][5]=ori[22];
cur[1][6]=ori[24];
dep=0;
memset(ans,0,sizeof(ans));
while(!dfs(1,8)) {
++dep;
}
if(!dep) {
puts("No moves needed");
}
else {
siji(i,1,dep) {
printf("%c",ans[i]+'A');
}
putchar('\n');
}
printf("%d\n",cur[0][2]);
}
return 0;
}
An addition chain for n is an integer sequence with the following four properties:
a0 = 1
am = n
a0 < a1 < a2 < ... < am-1 < am
For each k (1 <= k <= m) there exist two (not necessarily different) integers i and j (0 <= i, j <= k-1) with ak = ai + aj
You are given an integer n. Your job is to construct an addition chain for n with minimal length. If there is more than one such sequence, any one is acceptable.
For example, <1, 2, 3, 5> and <1, 2, 4, 5> are both valid solutions when you are asked for an addition chain for 5.
The input will contain one or more test cases. Each test case consists of one line containing one integer n (1 <= n <= 100). Input is terminated by a value of zero (0) for n.
For each test case, print one line containing the required integer sequence. Separate the numbers by one blank.
5
7
12
15
77
0
1 2 4 5
1 2 4 6 7
1 2 4 8 12
1 2 4 5 10 15
1 2 4 8 9 17 34 68 77
迭代加深搜索里比较简单的一道题
枚举深度然后搜索就可以,我这里单一的认为下一个数是相邻前一个数和某一个数相加,实际上应该会有别的情况,但是这种情况是大多数,可以简单优化一下不用深搜太多
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
int cur[105],dep=0;
bool dfs(int step) {
if(step>dep) {
if(cur[dep]==n) return true;
return false;
}
siji(i,0,step-1) {
if(cur[step-1]+cur[i]<=n) {
cur[step]=cur[step-1]+cur[i];
if(dfs(step+1)) return true;
}
}
return false;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
cur[0]=1;
while(scanf("%d",&n)!=EOF) {
if(n==0) break;
dep=0;
while(!dfs(1)) {
++dep;
}
siji(i,0,dep) {
printf("%d%c",cur[i]," \n"[i==dep]);
}
}
return 0;
}
Given S, a set of integers, find the largest d such that a + b + c = d where a, b, c, and d are distinct elements of S.
Several S, each consisting of a line containing an integer 1 <= n <= 1000 indicating the number of elements in S, followed by the elements of S, one per line. Each element of S is a distinct integer between -536870912 and +536870911 inclusive. The last line of input contains 0.
For each S, a single line containing d, or a single line containing "no solution".
5
2
3
5
7
12
5
2
16
64
256
1024
0
12
no solution
这道题我们可以考虑一半,a+b=d-c
把所有a+b哈希起来
然后枚举d c判断这个值有没有和a+b中的某个数相同
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
#define MOD 994711
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
ll a[2006];
struct node {
ll val;
int d,c;
int next;
}edge[1000005];
int head[MOD+15],sumedge;
void add(int u,ll v,int d,int c) {
edge[++sumedge].val=v;
edge[sumedge].next=head[u];
edge[sumedge].d=d;
edge[sumedge].c=c;
head[u]=sumedge;
}
void ins(ll v,int d,int c) {
int u=(v%MOD+MOD)%MOD;
add(u,v,d,c);
}
bool find(ll x,int d,int c) {
int u=(x%MOD+MOD)%MOD;
for(int i=head[u];i;i=edge[i].next) {
if(edge[i].val==x) {
if(d!=edge[i].d && c!=edge[i].c && d!=edge[i].c && c!=edge[i].d) {
return true;
}
}
}
return 0;
}
void solve() {
sumedge=0;
memset(head,0,sizeof(head));
siji(i,1,n) {
siji(j,i+1,n) {
ins(a[i]+a[j],i,j);
}
}
ll ans=-1000000000;
siji(i,1,n) {
siji(j,1,n) {
if(i==j) continue;
if(find(a[j]-a[i],j,i)) {
ans=max(ans,a[j]);
}
}
}
if(ans!=-1000000000)
printf("%lld\n",ans);
else
puts("no solution");
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
while(scanf("%d",&n)!=EOF) {
if(!n) break;
siji(i,1,n) scanf("%lld",&a[i]);
solve();
}
}
Given a list of N integers with absolute values no larger than 1015, find a non empty subset of these numbers which minimizes the absolute value of the sum of its elements. In case there are multiple subsets, choose the one with fewer elements.
The input contains multiple data sets, the first line of each data set contains N <= 35, the number of elements, the next line contains N numbers no larger than 1015 in absolute value and separated by a single space. The input is terminated with N = 0
For each data set in the input print two integers, the minimum absolute sum and the number of elements in the optimal subset.
1
10
3
20 100 -100
0
10 1
0 2
这道题无限WA……真是够了
我把前18个的2^18个都加进去,并没有去重或者同一值取最小值,直接二分
然而这样我找到了第一个大于等于它的然后用这个下标k-1再去更新
这是不对的,因为排完序之后同一个值数目较大的排在后边,我们需要再一次二分找到最前面等于k-1这个值的
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
//#define ivorysi
using namespace std;
typedef long long ll;
struct node {
ll val;
int num;
node () {};
node (ll v,int c) {
val=v;num=c;
}
bool operator < (const node &rhs) const {
if(val!=rhs.val) return val<rhs.val;
if(num!=rhs.num) return num<rhs.num;
return false;
}
}sum[2000005];
int tot,n;
ll a[55],ans;
int idx;
inline ll mabs(ll x) {
if(x<=0) return -x;
return x;
}
void update(ll t,int z) {
if(t<ans) {ans=t;idx=z;}
else if(t==ans) {idx=min(idx,z);}
}
void solve() {
int c=min(18,n);
int all=(1<<c);
ans=mabs(a[1]);
idx=1;
tot=0;
xiaosiji(i,1,all) {
ll tmp=0;
int cnt=0;
siji(j,1,c) {
if((i>>(j-1)) & 1){
tmp+=a[j];
++cnt;
}
}
update(mabs(tmp),cnt);
sum[++tot].val=tmp;
sum[tot].num=cnt;
}
sort(sum+1,sum+tot+1);
if(n<=18) {
printf("%lld %d\n",ans,idx);
return;
}
all=(1<<(n-18));
xiaosiji(i,1,all) {
ll tmp=0;
int cnt=0;
siji(j,1,n-18) {
if((i>>(j-1)) & 1) {
tmp+=a[j+18];
++cnt;
}
}
update(mabs(tmp),cnt);
int k1=lower_bound(sum+1,sum+tot+1,node(-tmp,0))-sum;
int k2=lower_bound(sum+1,sum+tot+1,node(sum[k1-1].val,0))-sum;
if(k1>tot) k1=tot;
if(k2>tot) k2=tot;
if(k1<1) k1=1;
if(k2<1) k2=1;
update(mabs(sum[k1].val+tmp),sum[k1].num+cnt);
update(mabs(sum[k2].val+tmp),sum[k2].num+cnt);
}
printf("%lld %d\n",ans,idx);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
while(scanf("%d",&n)!=EOF) {
if(n==0) break;
siji(i,1,n) scanf("%lld",&a[i]);
solve();
}
return 0;
}
In the game Lizard Era: Beginning the protagonist will travel with three companions: Lynn, Meliana and Worrigan. Overall the game has n mandatory quests. To perform each of them, you need to take exactly two companions.
The attitude of each of the companions to the hero is an integer. Initially, the attitude of each of them to the hero of neutral and equal to 0. As the hero completes quests, he makes actions that change the attitude of the companions, whom he took to perform this task, in positive or negative direction.
Tell us what companions the hero needs to choose to make their attitude equal after completing all the quests. If this can be done in several ways, choose the one in which the value of resulting attitude is greatest possible.
The first line contains positive integer n (1 ≤ n ≤ 25) — the number of important tasks.
Next n lines contain the descriptions of the tasks — the i-th line contains three integers li, mi, wi — the values by which the attitude of Lynn, Meliana and Worrigan respectively will change towards the hero if the hero takes them on the i-th task. All the numbers in the input are integers and do not exceed 107 in absolute value.
If there is no solution, print in the first line "Impossible".
Otherwise, print n lines, two characters is each line — in the i-th line print the first letters of the companions' names that hero should take to complete the i-th task ('L' for Lynn, 'M' for Meliana, 'W' for Worrigan). Print the letters in any order, if there are multiple solutions, print any of them.
3
1 0 0
0 1 0
0 0 1
LM
MW
MW
7
0 8 9
5 9 -2
6 -8 -7
9 4 5
-4 -9 9
-4 5 2
-6 8 -7
LM
MW
LM
LW
MW
LM
LW
2
1 0 0
1 1 0
Impossible
折半搜索意图很明显,注意一下要求最大的,而且特判一下n==1的情况
先dfs前一半把所有可能达到的值记到一个set里(记的是查分,方便查找)
然后dfs后一半去set里查有没有对应的差分
最后找到答案了再重新dfs前一半把答案还原出来
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <set>
#include <map>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
int l[35],m[35],w[35];
struct node {
int l,m,w;
node() {}
node(int li,int mi,int wi) {
l=li;m=mi;w=wi;
}
bool operator < (const node &rhs) const {
if(l!=rhs.l) return l<rhs.l;
if(m!=rhs.m) return m<rhs.m;
if(w!=rhs.w) return w<rhs.w;
return false;
}
bool operator == (const node &rhs) const {
return l==rhs.l && m==rhs.m && w==rhs.w;
}
}now;
set<node> s;
map<node,int> mmm;
char ans[35][3],tmpans[35][3];
int maxmum;
node rec;
bool dfs1(int dep,bool on,node cal) {
if(dep>n/2) {
if(on) {
if(cal==now) return 1;
}
else {
node k=node(0,now.m-now.l,now.w-now.m);
if(mmm.count(k)) {
mmm[k]=max(mmm[k],now.l);
}
else {
s.insert(k);
mmm[k]=now.l;
}
}
return 0;
}
now.l+=l[dep];
now.m+=m[dep];
if(on) {ans[dep][0]='L';ans[dep][1]='M';}
if(dfs1(dep+1,on,cal)) return true;
now.l-=l[dep];
now.m-=m[dep];
now.l+=l[dep];
now.w+=w[dep];
if(on) {ans[dep][0]='L';ans[dep][1]='W';}
if(dfs1(dep+1,on,cal)) return true;
now.l-=l[dep];
now.w-=w[dep];
now.m+=m[dep];
now.w+=w[dep];
if(on) {ans[dep][0]='M';ans[dep][1]='W';}
if(dfs1(dep+1,on,cal)) return true;
now.m-=m[dep];
now.w-=w[dep];
return false;
}
bool dfs2(int dep) {
if(dep<=n/2) {
node k=node(0,-now.m+now.l,-now.w+now.m);
set<node>::iterator iter=s.lower_bound(k);
if(iter!=s.end() && (*iter)==k) {
if(mmm[k]+now.l>maxmum) {
memcpy(ans,tmpans,sizeof(ans));
maxmum=mmm[k]+now.l;
rec.l=mmm[k];
rec.m=rec.l+k.m;
rec.w=rec.m+k.w;
}
return true;
}
return false;
}
bool res=0;
now.l+=l[dep];
now.m+=m[dep];
tmpans[dep][0]='L';tmpans[dep][1]='M';
if(dfs2(dep-1)) res=1;
now.l-=l[dep];
now.m-=m[dep];
now.l+=l[dep];
now.w+=w[dep];
tmpans[dep][0]='L';tmpans[dep][1]='W';
if(dfs2(dep-1)) res=1;
now.l-=l[dep];
now.w-=w[dep];
now.m+=m[dep];
now.w+=w[dep];
tmpans[dep][0]='M';tmpans[dep][1]='W';
if(dfs2(dep-1)) res=1;
now.m-=m[dep];
now.w-=w[dep];
return res;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
scanf("%d",&n);
maxmum=-100000000;
siji(i,1,n) {
scanf("%d%d%d",&l[i],&m[i],&w[i]);
}
if(n==1) {
int cnt=0;
if(l[1]==0) ans[1][cnt++]='L';
if(m[1]==0) ans[1][cnt++]='M';
if(w[1]==0) ans[1][cnt++]='W';
if(cnt<2) puts("Impossible");
else {
printf("%c%c\n",ans[1][0],ans[1][1]);
}
return 0;
}
now=node(0,0,0);
dfs1(1,0,(node){0,0,0});
now=node(0,0,0);
if(!dfs2(n)) {
puts("Impossible");
return 0;
}
else {
now=node(0,0,0);
dfs1(1,1,rec);
siji(i,1,n) {
printf("%c%c\n",ans[i][0],ans[i][1]);
}
}
return 0;
}