A

 按位讨论,取最小值;

B

 数据范围不大,首先要确定枚举角度;

 状压枚举palindromes的列比较科学;

 列确定后,目标就是求获得rcnt行的最小代价:

  dp[i][cnt]表示扫描到第i行,已经有cnt个满足要求的最小代价;

 根据对称性,只要扫描n/2行,而从第i行获得j个增益的代价cost[i][j],可以另外处理:

  当考虑cost[i][j]时,根据对称性,实际是考虑2行(i,n-i),从这2行获得增益的情况只有3种:0,1,2,

  然后,讨论每种情况下的代价:

    0, 只需保证列满足要求;

    1, 任一行满足要求,取最小值;

    2, 2行 同时满足要求;

  然后各种特判...

 #include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
#define maxn (1<<14)
#define INF 4000
#define rep(i,n) for(int i=0 ; i<(n) ; i++ )
class PalindromeMatrix {
public:
int minChange(vector <string>, int, int);
};
vector<int> valid;
int bit[maxn],n,m;
int check(int mask,int len) {
rep (i,len/) {
int p = mask&(<<i);
int q = mask&(<<(len-i-));
if (p!=q) return ;
}
return ;
}
void init() {
rep (i,maxn) {
if ((i<<)<maxn)bit[i<<] = bit[i];
if ((i<<|)<maxn)bit[i<<|] = bit[i]+;
}
rep (i,(<<m)) if (check(i,m)) valid.push_back(i);
}
int dp[][],cost[][];
void init(vector<string> A,int mask) {
rep (i,) rep (j,) dp[i][j]=INF;
rep (i,) rep (j,) cost[i][j]=INF;
rep (i,n/) {
string s1 = A[i];
string s2 = A[n--i];
// cout<<"s1:"<<s1<<endl;
// cout<<"s2:"<<s2<<endl;
int res = ;
// r=0
rep (j,m) if (mask&(<<j)) {
if (s1[j]!=s2[j]) res++;
}
cost[i][]=res;
// r=2
res = ;
//printf("cal:cost[%d][2]\n",i);
rep (j,m/) {
int a=j,b=m--j;
if ( (mask&(<<a)) || (mask&(<<b)) ) {
// printf("s1[%d]:%c s1[%d]:%c s2[%d]:%c s2[%d]:%c\n",a,s1[a],b,s1[b],a,s2[a],b,s2[b]);
int tmp = (s1[a]+s2[a]+s1[b]+s2[b]-*(int)'');
tmp = min(tmp,-tmp);
res += tmp;
}else {
if (s1[a]!=s1[b]) res++;
if (s2[a]!=s2[b]) res++;
}
}
cost[i][]=res;
// r=1,s1
res=;
rep (j,m/) {
int a=j,b=m--j;
if (s1[a] != s1[b]) {
if ( (mask&(<<a)) && (mask&(<<b)) ) {
int tmp = s1[a]+s1[b]+s2[a]+s2[b]-*'';
res += min(tmp,-tmp);
} else res ++;
} else {
if ( (mask&(<<a)) && (mask&(<<b)) ) {
int tmp = s1[a]+s1[b]+s2[a]+s2[b]-*'';
res += min(tmp,-tmp);
} else if ( (mask&(<<a)) ) {
res += (s1[a]!=s2[a]);
} else if ( (mask&(<<b)) ) {
res += (s1[b]!=s2[b]);
}
}
}
cost[i][]=res;
// r=1,s2
res=;
rep (j,m/) {
int a=j,b=m--j;
if (s2[a] != s2[b]) {
if ( (mask&(<<a)) && (mask&(<<b)) ) {
int tmp = s1[a]+s1[b]+s2[a]+s2[b]-*'';
res += min(tmp,-tmp);
} else res ++;
} else {
if ( (mask&(<<a)) && (mask&(<<b)) ) {
int tmp = s1[a]+s1[b]+s2[a]+s2[b]-*'';
res += min(tmp,-tmp);
} else if ( (mask&(<<a)) ) {
res += (s1[a]!=s2[a]);
} else if ( (mask&(<<b)) ) {
res += (s1[b]!=s2[b]);
}
}
}
cost[i][]=min(cost[i][],res);
}
}
void PrintMask(int mask) {//printf("var:%d mask:",mask);
while (mask) {
// printf("%d",mask&1?1:0);
mask>>=;
}//printf("\n");
}
int solv(vector<string> A,int nr,int nc) {
int ans = INF;
rep (s,(<<m)) if (bit[s]==nc) {
PrintMask(s);
init(A,s);
dp[][] = ;
rep (i,n/) rep (j,nr+)
if (dp[i][j]!=INF) {
rep (k,) {
int nxtj = min(nr,k+j);
dp[i+][nxtj] = min(dp[i+][nxtj],dp[i][j]+cost[i][k]);
}
}
ans = min(ans,dp[n/][nr]);
}
return ans;
}
int PalindromeMatrix::minChange(vector <string> A, int nr, int nc) {
init();
n = A.size();
m = A[].size();
int ans= solv(A,nr,nc);
return ans;
}

C

 刚开始想按b递增考虑,每加入一条线时的增加数应该很好算,后来发现情况非常复杂,很难发现结论.

 题解的结论是从交点个数得到的.

 尝试证明一下:

  加入一条直线时,每产生一个交点,就划分出一个新的区域,最后想象无穷远处有条封闭的边界,与延时到无限远的直线构成新的区域,

  所以结论为  1 + 不同的交点个数.

 

 #include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime> using namespace std; class LotsOfLines {
public:
long long countDivisions(int, int);
};
int gcd(int a,int b) {
if (b==) return a;
return gcd(b,a%b);
}
long long sum[][];
long long LotsOfLines::countDivisions(int A, int B) {
long long ans = ;
A-- , B--;
for (int q= ; q<=A ; q++ ) {
for (int p= ; p<=B ; p++ ) {
int x = gcd(p,q)==?:;
sum[q][p] = sum[q-][p] + sum[q][p-] - sum[q-][p-] + x;
}
}
for (int a= ; a<=A ; a++ ) {
for (int b= ; b<=B ; b++ ) {
ans ++;
if (a)
ans += + sum[a][b] + sum[a][B-b];
}
}
return ans;
} //Powered by [KawigiEdit] 2.0!

SRM 600 DIV1的更多相关文章

  1. topcoder srm 600 div1

    problem1 link 首先,如果一个数字的某一位是1但是$goal$的这一位不是1,那么这个数字是不用管它的.那么对于剩下的数字,只需要统计在$goal$为1的位上,这些数字对应位上也是1的数字 ...

  2. Topcoder SRM 600 div1题解

    日常TC计划正式启动! Easy(250pts): 题目大意:给你一个集合,里面一堆数,初始数为0,给你一个目标数,你可以选择集合中若干个数进行OR操作来得到目标数.问至少删去多少个数,使得你永远无法 ...

  3. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

  4. Topcoder Srm 726 Div1 Hard

    Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...

  5. SRM 146 DIV1 600

    Problem Statement      Masterbrain is a two player board game in which one player decides on a secre ...

  6. Topcoder SRM 584 DIV1 600

    思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...

  7. TopCoder SRM 722 Div1 Problem 600 DominoTiling(简单插头DP)

    题意  给定一个$12*12$的矩阵,每个元素是'.'或'X'.现在要求$1*2$的骨牌铺满整个矩阵, 'X'处不能放置骨牌.求方案数. 这道题其实和 Uva11270 是差不多的,就是加了一些条件. ...

  8. 图论 SRM 674 Div1 VampireTree 250

    Problem Statement      You are a genealogist specializing in family trees of vampires. Vampire famil ...

  9. SRM 600(1-250pt,500pt)

    DIV1 250pt 题意:给定一个vector<int>A,若能从里面选出一些数,使得他们按位或的值为x,则称x为吉利数.给定k,问最少要从A里面去掉多少个数,才能使k变为不吉利数. 解 ...

随机推荐

  1. Win32 的dll导入

    dll 文件可以导入变量,函数,和C++类,但是导入变量会使执行程序与dll紧耦合,而C++类导入则需要两个文件的开发商所用的编译器相兼容,所以做好只导入函数; 创建dll : 头文件:#ifdef  ...

  2. RSA 非对称加密 数字签名 数字证书

    什么是RSA加密算法 RSA加密算法是一种非对称加密算法,算法的数学基础是极大数分解难题. RSA加密算法的强度也就是极大数分解的难度,目前700多位(二进制)的数字已经可以破解,1024位认为是比较 ...

  3. Linux LVM 扩展磁盘分区

    系统:centos 6.3--新建分区 fdisk -l /dev/sdc       # 查看分区 fdisk /dev/sdc          # 创建分区 :n                 ...

  4. yii2 添加模块过程

    本文以Yii2基本应用程序模板为例,介绍下向该框架下加入新模块的过程: 1. 新建模块相关目录与文件 step 1: 新建目录结构   首先在根目录下新建modules目录,然后在该目录下面添加模块目 ...

  5. sql 判断表、列、视图等是否存在

    1 判断数据库是否存在 if exists (select * from sys.databases where name = '数据库名')     drop database [数据库名] 2 判 ...

  6. 如何在github上传自己的项目

    1.首先在github创建自己的账号. 2.下载github for windows 客户端 (备注:这里我的电脑是windows系统的) ,不要下载错了,网上下载的应该是这样的安装程序 3.安装gi ...

  7. 禁止Windows远程桌面拷贝文件

    通过组策略,我们可以解决以上问题,开始菜单运行输入gpedit.msc,进入“计算机配置”项,按顺序进入“管理模板”.“windows组件”.“终端服务”.“客户端/服务器数据重定向”.在详细描述栏中 ...

  8. IOS创建开源库步骤,提交cocoa pods官网,别人可以使用

    1.打开终端进入某个目录执行  pod lib create BMBlinkButton,按命令步骤执行. 2.目录结构 3.修改BMBlinkButton.podspec文件 4.进入Example ...

  9. WebBasic-表单

    用来提交数据 <form></form> 属性:action:提交的url  method:表单数据提交的方式  enctype:表单数据的编码方式 表单控件 --input元 ...

  10. QT5-控件-QSpinBox和QDoubleSpinBox(用于通过控件调整整数和小数)

    #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QSpinBox> #in ...