更棒的算法
nuggets
//这居然过了......
sort(arr, arr+n);
if (n == 1 || arr[0] == 1 || alleven)
{
fout << "0" << endl;
}//枚举了这三种情况后生成(背包)200000以前的所有,如果mp = 200000-1那么输出0,否则mp...
结论(之前数论白学了系列QAQ)
- 有两个数p,q,且gcd(q,p)=1,则最大无法表示成px+qy(x>=0,y>=0)的数是pq-q-p
- 而且数越多,这个值只会越小。
- 取上界为256*256-256*2 = 65024//这也就证明了..上面的ac
- 判断无限解可以按上面的方法,另外也可以算所有的数的最大公约数。如果不是1,也就是说这些数不互质,那么不被这个最大公约数整除的数一定构造不出来。当且仅当这种情况会有无限解。
- 优化算法 这道题其实是可以做到O(N^2)。 令A1表示所有鸡块中最小的那种, 如果有连续A1个数都可以打到,那么之后所有的数都是可以达到的(每次加上A1就行了)。
标准解法用了尝试过的循环数组
while (pos < 2000000000) { /* bound as stated */ /* if last 256 were all possible, we are done */ if (pos - last > 256) break; if (!cando[lv]) last = pos; /* this isn't possible, update last impossible */ else { /* this is possible */ cando[lv] = 0; /* mark pos+256 as impossible */ /* mark pos + size as possible for each package size */ for (lv2 = 0; lv2 < nsize; lv2++) cando[(lv+sizes[lv2])%256] = 1; } /* update lv & pos */ lv = (++pos) % 256; }
另外感觉USACO的机器升级了XD
fence6
给出n条边长度,每条边两个端点相交边的序号,求最小环
这道题难点有二:
序号很麻烦..坑了一晚上
主要是不是逆时针或者顺时针给的,需要判断交点
O(n2)扫两遍,用一个变量标志id
//扫一个数组, for (int i = 1; i <= totF; ++i) { if (F[i].rr == 0)//这样id一定最小 { F[i].rr = ++d;//新的id for (int p = 1; p <= F[i].r[0]; p++) { int k = F[i].r[p];//更新rr位置 //确认对应位置,给id int inRR = false; for (int s = 1; s <= F[k].r[0]; s++) { if (F[k].r[s] == i) { inRR = true; break; } } if (inRR) { F[k].rr = d; continue; } F[k].ll = d; } } if (F[i].ll == 0) { //和上面相同 } }
最小环
有了id之后就可以最小环了
思路是枚举每一条边
oo
最短路FLOYD改进版本可以过
for (int eg = 1; eg <= totF; eg++) //枚举边 { int fr = F[eg].ll,to = F[eg].rr; //初始化距离矩阵,该边为oo for (int i = 1; i <= d; i++) { for (int j = 1; j <= d; j++) { dis[i][j] = inf; } //dis[i][i] = 0; } for (int i = 1; i <= totF; i++) { if (i != eg) { int fr = F[i].ll,to = F[i].rr; dis[fr][to] =dis[to][fr] = F[i].len; } } //floyd for (int by = 1; by <= d; by ++) { for (int fr = 1; fr <= d; fr ++) { for (int to = 1; to <= d; to ++) { dis[fr][to] = min(dis[fr][to],dis[fr][by]+dis[by][to]); } } } //当有另一条路过去的时候,那么就是最小环的一半 for (int by = 1; by <= d; by++) { if(by != fr && by != to){ ans = min(ans, F[eg].len+ dis[fr][by] + dis[by][to]); } } }
- 当然,这是单源最短路径,所以可以用SPFA,dijkstra来优化速度
- 据说搜索+剪枝也能过
//nocow上没有id化的代码 int dijkstra(int z){ int i,j,k; for(i=1;i<=n;i++){dis[i]=MAX;isi[i]=0;}//初始化 for(i=1;i<=map[0][z][0];i++) { bef[map[0][z][i]]=z; dis[map[0][z][i]]=len[z]; } while(1){ j=0; k=MAX; for(i=1;i<=n;i++) if(dis[i]<k && isi[i]==0){ j=i; k=dis[i]; }//最近d if(j==0)break;//找不到 if(j==z)return dis[z];//当前 isi[j]=1;//最优标记 for(i=1;i<=map[0][j][0];i++) if(map[0][j][i]==bef[j])break; if(i==map[0][j][0]+1) k=0;//0方向 else k=1;//1方向 for(i=1;i<=map[k][j][0];i++){ if(dis[map[k][j][i]]>dis[j]+len[j]){ dis[map[k][j][i]]=dis[j]+len[j]; bef[map[k][j][i]]=j; } } } return MAX; }
- 其实这道题时间大多数花在纠结是用vector还是set
- 搜索也写烂了几次,所以其实很多看起来很炫酷的东西其实并不重要,重要的是即使是枚举也先要实现代码.
今(昨)天有一个很开心的事是发现xcode怎么输入输出不是绝对路径的文件了23333