A

  首先发现对于2操作,每种素因子可以单独考虑,然后取出步数最多的计入答案,然后分别加上对每种素因子的1操作;

  第二步我犯了个错误,以为最优方案是把素因子指数按二进制操作,在1的位置执行1操作,0的位置执行2操作倍增;

  然后发现是错的,执行一次1操作后,之后的2操作可以完全代替1操作,这样可以节省对其他素因子的1操作...

  

 int getbit(int x)
{
int cur=,res=;
while (cur<x) cur+=cur,res++;
return res;
}
int BigFatInteger::minOperations(int A, int B)
{
initprm();
int ans=,p=;
for (int i= ; i<cnt ; i++) if (A%prm[i]==)
{
int t=;
while (A%prm[i]==) A/=prm[i],t+=B;
ans ++;
p = max(p,getbit(t));
}
return ans+p;
}

B

  题解的思路真的很棒...

  首先为了简化问题,需要猜想+证明一些性质:

  1) 每条边必须是整数; (无理数+无理数=无理数...)

  2) L不能是奇数; (基于性质1,因为多边形形成闭合回路,坐标的奇偶变化是偶数,x0->x0,y0->y0)

  接下来发现L为偶数的时候可以构造出rectangle,于是问题化简为找到一个满足要求的triangle.

  然后根据格点的离散性,对称性,可以把可能的点集缩小,最后o(n2)的暴力枚举/打表.

 struct node{int x,y;};
vector<node>p;
vector<int>d;
int sqt[INF+];
bool check(int x,int y)
{
int dist = x*x+y*y;
if (dist>=INF || !sqt[dist]) return false;
d.push_back(sqt[dist]);
return true;
}
int getdist(node a,node b)
{
int tmp = (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
if (tmp>=INF || !sqt[tmp]) return INF;
return sqt[tmp];
}
double find(int l)
{
double res = -1e20;
for (int x= ; x<=l/ ; x++ )
for (int y= ; y<=l/ ; y++ )
if (check(x,y)) p.push_back((node){x,y});
int n = p.size();
for (int i= ; i<n ; i++ )
for (int j=i+ ; j<n ; j++ ) if(d[i]+d[j]<l)
{
int t = getdist(p[i],p[j]);
if (d[i]+d[j]+t!=l) continue;
if (p[i].y*p[j].x==p[i].x*p[j].y) continue;
int tmp = max(d[i],max(d[j],t)) - min(d[i],min(d[j],t));
if (res< || res>tmp) res=tmp;
}
return res;
}
double FindPolygons::minimumPolygon(int L)
{
if (L% || L<) return -1.0;
else
{
for (int i= ; i<= ; i++ ) sqt[i*i]=i;
double ans = find(L);
if (ans>=0.0) return ans;
else return (L%==)?:;
}
}

C

  不在info中的点可以乘一个排列数,问题化简为求满足info的方案数.

  如果确定了info1[i]为a,那么info2[i]只能选取以a为前缀的集合...

  如果info2[i]在info1中还出现过,可以递推下去考虑...

  然后就会发现这个问题涉及到一个树形结构.

  把所有string造成一棵前缀树,重述问题就是:假设info1[i]位置放a,info2[i]位置只能在a的子树中.

  f(x,mask) 表示当前在第i个节点,分配mask集合的方案数.

  答案就是f(root,11..1).

  对于每个f(x,mask)有两种决策,分配给x,不分配.

  然后解决子问题g(x,son,mask2) 表示给x的son分配剩下mask的方案数.

  优化:预处理所有合法状态的转移.

  

 const int mod = (int)1e9 + ;
class SimilarNames {
public:
int count(vector <string>, vector <int>, vector <int>);
};
vector<int>valid,nxt[MASK],sub[MASK],e[maxn];
map<int,int>ha;
const int root = ;
int n,m,k,id[MASK];
int getk(vector<int>u,vector<int>v){
for (int i= ; i<m ; i++ ){
if (!ha.count(u[i])) u[i]=ha[u[i]]=ha.size()-;
if (!ha.count(v[i])) v[i]=ha[v[i]]=ha.size()-;
}
return ha.size();
}
void buildtree(vector<string>names){
sort(names.begin(),names.end());
for (int i= ; i<n ; i++ ){
int fa = root;
for (int j=i- ; j>= ; j-- )
if (names[i].substr(,names[j].size())==names[j]){
fa = j;break;
}
e[fa].push_back(i);
}
}
void pretreat(vector<int>u,vector<int>v){
memset(id,-,sizeof(id));
for (int i=,j ; i<(<<k) ; i++ ){
for ( j= ; j<m ; j++ ){
int p = <<ha[u[j]];
int q = <<ha[v[j]];
if ((i&p) && ((i&q)==)) break;
}
if (j==m) {
valid.push_back(i);
id[i] = valid.size()-;
}
}
for (int i= ; i<(int)valid.size() ; i++ )
for (int j= ; j<k ; j++ ) if(valid[i]&(<<j)){
if (id[valid[i]^(<<j)]!=-)
nxt[i].push_back(id[valid[i]^(<<j)]);
}
for (int i= ; i<(int)valid.size() ; i++ )
for (int j=valid[i] ; ; j=(j-)&valid[i]){
if (id[j]!=- && id[valid[i]-j]!=-)
sub[i].push_back(id[j]);
if (!j) break;
}
}
int f[maxn][MASK],g[maxn][MASK];
int add(int &x,int y){
x += y;
while (x>=mod) x-=mod;
return x;
}
int getg(int cur,int s,int mask){
if (s>=) return g[e[cur][s]][mask];
else return !valid[mask];
}
void dfs(int cur){
int s = e[cur].size();
for (int i= ; i<s ; i++ )
dfs(e[cur][i]); for (int i= ; i<s ; i++ ){
for (int j= ; j<(int)valid.size() ; j++ ){
for (int x= ; x<(int)sub[j].size() ; x++ ){
int A = valid[j];
int B = valid[sub[j][x]];
int p = getg(cur,i-,id[B]);
int q = f[e[cur][i]][id[A-B]];
g[e[cur][i]][j] = add(g[e[cur][i]][j],((llong)p*q)%mod);
}
}
} for (int i= ; i<(int)valid.size() ; i++ ){
f[cur][i] = add(f[cur][i],getg(cur,s-,i));
if (cur!=root){
for (int j= ; j<(int)nxt[i].size() ; j++ )
f[cur][i] = add(f[cur][i],getg(cur,s-,nxt[i][j]));
}
}
}
int SimilarNames::count(vector <string> names, vector <int> u, vector <int> v){
n = names.size();
m = u.size();
k = getk(u,v);
buildtree(names);
pretreat(u,v);
dfs(root);
llong ans = f[root][id[(<<k)-]];
for (int i=n-k ; i> ; i-- ) ans = (llong)(ans*i)%mod;
return (int)ans;
}

  

SRM 599 DIV1的更多相关文章

  1. Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

    据说做TC题有助于提高知识水平? :) 传送门:https://284914869.github.io/AEoj/index.html 转载请注明链接:http://www.cnblogs.com/B ...

  2. Topcoder SRM 643 Div1 250<peter_pan>

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

  3. Topcoder Srm 726 Div1 Hard

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

  4. 图论 SRM 674 Div1 VampireTree 250

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

  5. SRM 583 DIV1

    A 裸最短路. class TravelOnMars { public: int minTimes(vector <int>, int, int); }; vector<int> ...

  6. SRM 590 DIV1

    转载请注明出处,谢谢viewmode=contents">http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlov ...

  7. Topcoder SRM 602 div1题解

    打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...

  8. 状态压缩DP SRM 667 Div1 OrderOfOperations 250

    Problem Statement      Cat Noku has just finished writing his first computer program. Noku's compute ...

  9. 数学 SRM 690 Div1 WolfCardGame 300

    Problem Statement      Wolf Sothe and Cat Snuke are playing a card game. The game is played with exa ...

随机推荐

  1. C++ lambda 表达式传递的变量默认不可变

    我遇到例如以下问题: int count=0; listener->onTouchMoved=[count](Touch* t,Event* e){ count++; log("onT ...

  2. oracle group by rollup,decode,grouping,nvl,nvl2,nullif,grouping_id,group_id,grouping sets,RATIO_TO

    干oracle 047文章12当问题,经验group by 声明.因此邂逅group by  rollup,decode,grouping,nvl,nvl2,nullif,RATIO_TO_REPOR ...

  3. Java基础知识强化48:Java中哈希码

    1.概念:      哈希其实只是一个概念,没有什么真实的指向.它的目的是保证数据均匀的分布到一定的范围内.所以不同数据产生相同的哈希码是完全可以的.      现在是站在JAVA虚拟机的角度来看内存 ...

  4. script 表单验证

    表单验证:一.非空验证:1.内容是不是空的.判断值的长度是不是0.length属性.压缩空格的函数. 2.内容是不是改变了. 二.对比验证:1.验证两个控件值的关系(相同,大小) 2.验证控件的值与某 ...

  5. css伪类选择器详细解析及案例使用-----伪类选择器(2)

    结构伪类选择器: <div> <ul> /*ul:only-of-type*/ <li>one</li> /*li:first-child li:nth ...

  6. Set,Map数据结构

    /*Set : 多个value的集合, value不重复Map : 多个key-value对的集合, key不重复 1. Set容器 1). Set() 2). Set(array) 3). add( ...

  7. Ubuntu 添加sudo用户

    第一种方法: 添加sudo用户 当你安装Ubuntu的时候,它会自动添加第一个用户到sudo组,允许这个用户通过键入其自身帐户密 码来获得超级用户(root)身份.然而,系统不会再自动添加其他的用户到 ...

  8. js中substring/substr和C#中Substring的用法

    一:在js中截取字符串的方法有两个:substring和substr 1.方法: substring(int stringIndex,[int endIndex]) 截取从索引为stringIndex ...

  9. C#--接口的实现

    接口: 不允许使用访问修饰符,所有接口成员都是公共的. 接口成员不能包含代码体. 接口不能定义字段成员. 接口成员不能使用关键字static,vritual,abstract,sealed来定义. 类 ...

  10. Enumeration

    Interface Enumeration<E> hasMoreElements() boolean hasMoreElements()    仅当此枚举对象包含至少一个以上元素为真:否则 ...