整数拆分

[题目描述]

有一个整数n(1≤n≤10^9),你需要将n分解成若干互不相等的正数的和。怎么分?

[输入描述]

一行一个数n.

[输出描述]

你需要输出满足条件的分解中最大数的最小值.

[样例输入]

1

[样例输出]

1

 

Tip of OJ

由于遭遇了各种坑爹事件(!|_*)

我决定在这简要统计各个Oj评测机与评测标准:

Oj评测机与评测标准
OJ 评测机 评测标准 网站功能 使用感受
hduhdu_logo   __int64    
Poj        
SPOJ     英文拙计
CF   可以看别人代码   
BZOJ    cout偶尔会WA/T    
USACO        
RQNOJ        
TopCoder     Java支持   
Tyvj     捏泡泡功能不错   

APIO 2013 游记

难得去一回APIO,结果各种卖萌……

Day 1:上午坐飞机到了北京,下榻,中午吃饺子,我点了2*2两,结果连3两都没吃完,被黄哥哥D……

Day 2:上午听了提交答案题做法(值得听的是怎样截取cheker.exe的内容与怎样在C++中运行cmd,中途说到sprintf("xxx%d%d",a,b);中的sprintf()在cassert库中,我明明经常用这句,可是不知道居然还要这个库……),下午讲了Ural(不是UVa)题目选讲和某场Uva比赛,各种欢乐。

Day 3:去考试了,拿到看完题目后先去做第三道X floyd&bellman,之后觉得第一题模拟可做,就去敲第1题,结果从10点敲到1点(1点30交),终于挑出来了,马不停蹄去写第3题7,8的骗分,赶在’悲惨的白屏-某提交页面崩溃’前交了,Hgh表示最后因为白屏啥也没交上去,只有之前随手交的暴力……

          为什么第一题要敲那么久(别人10min暴力)啊,为什么DevC++各种傲娇,缩进各种乱入啊……@#@$#Adsa*

          结果成绩出来了:第一题15+第三题52,我是不是应该庆幸好歹自己交上去了?……(早知道去写最后一题X MDj,说不定最后一题还能80多分啊……,第一题交-1就10分好吗?第三题k=1写一下就15分,干嘛把时间都发在模拟上,干嘛打那么久我XX……)

         之后评讲走错教室,差点听了一节概率数学各种囧……话外音:什么时候把教室改到101的?

         晚上炫教请客吃饭,鱼丸没来,本着膜拜教主,人人有责的原则,不打算让他掏钱,但最后还是掏了(膜拜奖学金2.5*104的)……

         找柯黑要了Mingw,从此怒转Codeblocks,从此再也不用担心Dev傲娇。

Day 4:今天刘定峰神犇和天犇组队北大“葫芦杯”ACM,留下我们几个弱菜听讲座。

                上午讲了线段树(被虐)。中午和Hgh等人去北大外面吃饭,结果走了10min发现越走越荒凉……无奈掉头,结果我们居然走到了中关村?之后我们到美食广场吃了<?打卤面?>的不明物,回去(已经迟到了,只好用秘籍:go back door.)结果一来就发现居然在打Dota?(我们好像错过了什么),之后讲了团体对抗赛的背景(猩猿星争霸)之所以叫这个名字是因为我们将来从事的某种工作的一个字有关(懂了~够内涵)

                 明明说要讲数论?之后果断讲了,果断没听懂……<balabala……>

                 晚上APIO闭幕式发奖状,我考得这么惨居然还能Ag?(Ag垫底……)膜拜福建金牌以及帮他拿奖状的(没来,去看《猩猿争霸》了).

                晚上打CF,柯黑神翻译,结果各种错……详见CF 303B

               之后我才知道老师找我们一直打不通电话,快急疯了……(明明就在宾馆)

                后半夜打《三国杀?》,各种卖队友,不会打三国杀显露无遗……

               最后居然快打到天亮了,行李还没整我A&*(&9

Day 5:做飞机回去,中途2人失重。于是天犇去追那2人,老师又叫黄考古去追天犇,之后我去追黄考古被拦(师云:再追人就没了),难以至今的是鱼丸神秘出现在机场大巴上?(它是怎么摸进来的)

               于是飞机上又看了一遍《十二生肖》

终于知道为什么那么多大牛在Wp上很少发博客的真正原因

最近用了很久一段时间的WP,每天尽忙活插件了……

忽然想起大牛Blog的一个共同规律(前面一堆解报,之后好像有点跑题,来点WP相关,OSU,耳机购买策略,怎么磨咖啡,最后很开心的发表其它各类散文/游记/OI心路历程/CF 出题报告(给教主跪烂,给WJMZBMR跪烂……,博客成给别人看的了)

这才发现不同的Bloging方式差别甚远

Blog阶段//

1.Csdn,博客园党:解报解报解报解报解报解报……基本上这种专业Blog会发展成外人看来Orz的Blog狂……实际上只是没做一道题都把代码,题目往上贴,在写2句解题感悟啥的……这种人博客文章是用百计数的,到最后会发展成解报题库(类似Wiki)

2.baidu:在baidu空间升级后各种NTR,转移为WP党……

3.blogbus,点点,Qzone:这种地方真心不适合发解报啊亲……

4.网易,sina:这种地方当当从Blog来说真的不错,毅力指数较高(有很多同党)

Final.Wp党-可以肯定的是前面几种人最后都会陆续迁到这,然后不挪窝了……但是Wp在我看来真心不适合搞解报(之所以这么说是因为使用经验,Wp绝没有一个现成的成体制的社区来的方便,因此你总会感觉是你自己一个人更新,自得其乐,你开始真正领悟啥叫Blog了……)

最后说一句,最好不要在这里发解报[exp]要发左转[/exp]

LA 5916(GCD Guessing Game-质数分组)

现在有一个数x,1 ≤ x≤ n,告诉你n,每次你可以猜一个数y,如果x==y则结束,否则返回gcd(x,y),问最少只要几次就可以保证猜出答案。

Input 

The input file contains several test cases, each of them as described below.

The input contains one integer n2$ \le$n$ \le$10000.

Output

For each test case, write to the output on a line by itself.

Output one integer -- the number of guesses Andrew will need to make in the worst case.

 

Sample Input

6

 

Sample Output

2

首先把所有n以内素分组,每次询问一组素数的积——根据Gcd的性质确定这个数

每次贪心拿一个大质数与一堆小质数配(最右*最左)

 

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN (10000)
#define eps (1e-9)
#define For(i,n) for(int i=1;i< =n;i++) #define ForD(i,n) for(int i=n;i;i--) #define Fork(i,k,n) for(int i=k;i<=n;i++) int n,a[MAXN],size=0; bool b[MAXN]; int main() { memset(b,0,sizeof(b));b[1]=1; Fork(i,2,MAXN) { if (!b[i]) b[i]=1,a[++size]=i; For(j,size) { if (i*a[j]>MAXN) break;
b[i*a[j]]=1;
if (!i%a[j]) break;
}
}
// For(i,100) cout< >n)
{
int i=0,head=1,tail=size;
while (a[tail]>n) tail--;
while (head< =tail) { int p=a[tail]; while (p*a[head]<=n) p*=a[head++]; tail--;i++; } cout<

 

BZOJ 1013([JSOI2008]球形空间产生器sphere-gauss消元练习)

1013: [JSOI2008]球形空间产生器sphere

Time Limit: 1 Sec  Memory Limit: 162 MB

Submit: 1181  Solved: 654

[Submit][Status][Discuss]

Description

有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。

Input

第一行是一个整数,n。 接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。每一个实数精确到小数点后6位,且其绝对值都不超过20000。

Output

有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点后3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。

Sample Input

2
0.0 0.0
-1.0 1.0
1.0 0.0

Sample Output

0.500 1.500

数据规模:
对于40%的数据,1<=n<=3
对于100%的数据,1<=n<=10
提示:给出两个定义:
1、 球心:到球面上任意一点距离都相等的点。
2、 距离:设两个n为空间上的点A, B的坐标为(a1, a2, …, an), (b1, b2, …, bn),则AB的距离定义为:dist = sqrt( (a1-b1)^2 + (a2-b2)^2 + … + (an-bn)^2 )

 

高斯消元

显然可以消成Σ(pi-qi)xi=1/2*Σ(pi^2-qi^2)

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN (10+10)
#define MAXAi (20000)
#define eps (0.0000001)
#define For(i,n) for(int i=1;i< =n;i++) double sqr(double x){return x*x;} int n; double a[MAXN][MAXN],f[MAXN][MAXN]={0.0}; int gauss() { For(i,n) { if (abs(f[i][i])abs(f[p][i])) j=p;
swap(f[p],f[i]);//Waiting for change
}
if (abs(f[i][i])>n;
For(i,n+1) For(j,n) cin>>a[i][j];
For(i,n) For(j,n) f[i][j]=a[i][j]-a[i+1][j],f[i][n+1]+=sqr(a[i][j])-sqr(a[i+1][j]);
For(i,n) f[i][n+1]/=2;
/*
For(i,n)
{
For(j,n+1) cout<

你能看得出这些问题共同的做法吗?1

Program 1:

Just The Mice NBUT1312

nbut1312把肉和老鼠分开,至少要描几条(网格)线?

Program 2:

k-road Prob

K-road从A点到B点走k次,每次只能向左,下,假定每个格子上都有一个整数,问能走过的最大的数的和是多少?

Program 3:

k-road Prob 2

K-road从A点到B点走k次,每次只能向左,下,假定每个格子上都有一个整数,问能走过的最大的数的积是多少?

Program 4

Catching Curl

bzoj1001这图相信大家都见过了XD……题目略

 

数位和乘积(高精组合数学)

Problem 3 数位和乘积(digit.cpp/c/pas)

【题目描述】

一个数字的数位和乘积为其各位数字的乘积。求所有的N位数中有多少个数的数位和乘积恰好为K。请注意,这里的N位数是可以有前导零的。比如01,02视为二位数,但是他们的数位和乘积都是0。

【输入格式】

一行两个整数N,K

【输出格式】

一个行一个整数表示结果。

【样例输入】

2 3

【样例输出】

2

【样例输入2】

2 0

【样例输出2】

19

【数据范围】

对于20%:N <= 6。

对于50%:N<=16

存在另外30%:K=0。

对于100%:N <= 50,0 <= K <= 10^9。

法1:

k=0时,ans=10^n-9^n

否则就用记忆化搜索填1..9的个数

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN (50+10)
#define F (10000)
int n,k;
struct highn
{
int len,a[900];
highn():len(1){memset(a,0,sizeof(a));}
highn(int x)
{
memset(a,0,sizeof(a));
int i=0;
while (x)
{
a[++i]=x%F;
x/=F;
}
len=i;
}
void print()
{
printf("%d",a[len]);
for (int i=len-1;i;i--)
{
// if (a[i]<10000) printf("0");
if (a[i]<1000) printf("0");
if (a[i]<100) printf("0");
if (a[i]<10) printf("0");
printf("%d",a[i]);
}

}
friend highn operator+(highn& a,highn& b)
{
highn c;
int maxlen=max(a.len,b.len);
for (int i=1;i< =maxlen;i++) { c.a[i]=c.a[i]+a.a[i]+b.a[i]; if (c.a[i]>F)
{
c.a[i+1]+=c.a[i]/F;
c.a[i]%=F;
}
}
c.len=maxlen+1;
while (!c.a[c.len]&&c.len>1) c.len--;
return c;

}
friend highn operator-(highn& a,highn& b)
{
highn c;
int maxlen=a.len;
for (int i=1;i< =maxlen;i++) { c.a[i]+=a.a[i]-b.a[i]; if (c.a[i]<0) { c.a[i+1]--; c.a[i]+=F; } } c.len=maxlen; while (!c.a[c.len]&&c.len>1) c.len--;
return c;
}
friend highn operator*(highn& a,highn& b)
{
highn c;
for (int i=1;i< =a.len;i++) { for (int j=1;j<=b.len;j++) { c.a[i+j-1]+=a.a[i]*b.a[j]; if (c.a[i+j-1]>F)
{
c.a[i+j]+=c.a[i+j-1]/F;
c.a[i+j-1]%=F;
}
}
}
c.len=a.len+b.len+1;
while (!c.a[c.len]&&c.len>1) c.len--;
return c;
}

};
highn pow2(highn a,int b)
{
highn c;
if (!b) return 1;
if (b%2)
{
c=pow2(a,b/2);
c=c*c;
c=c*a;
}
else
{
c=pow2(a,b/2);
c=c*c;
}
return c;
}
int a[11],tot,b[11];
highn ans,C[51][51];
void dfs(int deep,highn rel,int hasget)
{
if (n

法2:

f[i][j][k][l][m]表示填到第i个数,2,3,5,7分别用j,k,l,m个的方案数

考虑后面填1..9的情况(显然不可能填0)

Bug:n=50,C(n,m)最大为C(50,25),可用long long.

----

----

法3:

容易发现

k=2^a*3^b*5^c*7^d时才有解

而且5,7取了当且只当数位为5,7的情况.

2-2,4,6,8

3-3,6,9

5-5

7-7

故可只考虑2,3,不考虑5,7

f[i][j]k]表示i位,取了j个2和k个3后的方案数,

因为可以用1填充,

所以答案=∑f[p][j][k]*C(p,j+k)*C(n,a[5])*C(n-a[5],a[7]) (p<=n-a[5]-a[7])

BZOJ 1507(文字编辑器-块状链表)

1507: [NOI2003]Editor

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 922  Solved: 323
[Submit][Status][Discuss]

Description

很久很久以前,DOS3.x 的程序员们开始对 EDLIN 感到厌倦。于是,人们开始纷纷改用自己写的文本编辑器……
多年之后,出于偶然的机会,小明找到了当时的一个编辑软件。进行了一些简单的测试后,小明惊奇地发现:那个软件每秒能够进行上万次编辑操作(当然,你不能手工进行这样的测试)!于是,小明废寝忘食地想做一个同样的东西出来。你能帮助他吗?
为了明确任务目标,小明对“文本编辑器”做了一个抽象的定义:
文本:由 0 个或多个字符构成的序列。这些字符的 ASCII 码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。
光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。
文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下六条操作的程序。
如果这段文本为空,我们就说这个文本编辑器是空的。

你的任务是:
 建立一个空的文本编辑器。
 从输入文件中读入一些操作指令并执行。
 对所有执行过的 GET 操作,将指定的内容写入输出文件。

Input

第一行是指令条数 t,以下是需要执行的 t 个操作。其中:
为了使输入文件便于阅读,Insert 操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例)。
除了回车符之外,输入文件的所有字符的 ASCII 码都在闭区间[32, 126]内。且行尾没
有空格。
这里我们有如下假定:
1. MOVE 操作不超过 50000 个,INSERT 和 DELETE 操作的总个数不超过 4000,PREV 和 NEXT 操作的总个数不超过 200000。
2. 所有 INSERT 插入的字符数之和不超过 2M(1M=1024*1024),正确的输出文件长度不超过 3M 字节。
3. DELETE 操作和 GET 操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。
4. 输入文件没有错误。
对 C++选手的提示:经测试,对最大的测试数据使用 fstream 进行输入有可能会比使用 stdio 慢约 1 秒,因此建议在可以的情况下使用后者。

Output

输出每行依次对应输入文件中每条GET指令的输出。

Sample Input

15
Insert 26
abcdefghijklmnop
qrstuv wxy
Move 16
Delete 11
Move 5
Insert 1
^
Next
Insert 1
_
Next
Next
Insert 4
.\/.
Get 4
Prev
Insert 1
^
Move 0
Get 22

Sample Output

.\/.
abcde^_^f.\/.ghijklmno

这题我是用块状链表做的

块状链表的复杂度大约是O(√n)

一定要尽可能将块分成长度为√tot的,balance()时要把所有的长度分为介于1/2√tot-2√tot之间

另外merge时要注意先把cur移动再重载合并格的长度(不容易查出错,不知为何,加错也能过8个点)

要参考老董的讲解nocow的模板

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXP (1024*1024)
#define MAXN (2900)
struct block
{
int n;
char a[MAXN];
block *next,*pre;
block():n(0){next=pre=NULL;}
}*first;
block* q[MAXN];
int size=0,tot=0;
void del(block *x)
{
q[++size]=x;
if (x->pre) x->pre->next=x->next;
if (x->next) x->next->pre=x->pre;
if (x==first) first=x->next;
}
block *newblock()
{
if (size) return q[size--];
block *x=new block();
return x;
}
void link(block *a,block *b)
{
if (a) a->next=b;
if (b) b->pre=a;
}
void spilt(block *x,int nowsize)
{
if (!nowsize||nowsize==x->n) return;
block *tmp=x->next;
x->next=newblock();
block *x2=x->next;
x2->n=x->n-nowsize;
for (int i=1;i< =x2->n;i++) x2->a[i]=x->a[nowsize+i];
x->n=nowsize;
link(x2,tmp);
link(x,x2);
}
struct cursor
{
int n;
block *ll;
cursor():n(0){ll=first; }
void pre()
{
n--;
if (n<0)
{
ll=ll->pre;
n=ll->n-1;
}
}
void next()
{
n++;
if (n>ll->n)
{
ll=ll->next;
n=1;
}
}
void move(int k)
{
n=k,ll=first;
while (n>ll->n)
{
n-=ll->n;
ll=ll->next;
}
}
}cur;
void get(cursor cur,int k)
{
int p=cur.ll->n-cur.n;
if (p>=k)
{
for (int i=cur.n+1;i< =cur.n+k;i++) printf("%c",cur.ll->a[i]);
}
else
{
for (int i=cur.n+1;i< =cur.ll->n;i++) printf("%c",cur.ll->a[i]);
cur.ll=cur.ll->next;cur.n=0;
get(cur,k-p);
}
}
void merge(block *x)
{
if (!x->next) return;
for (int i=1;i< =x->next->n;i++) x->a[x->n+i]=x->next->a[i];
if (cur.ll==x->next)
{
cur.ll=x;
cur.n+=x->n;
}
x->n+=x->next->n;
del(x->next);
}
void balance()
{
int maxsize=min(MAXN,(int)sqrt(tot)*2);
int minsize=(int)sqrt(tot)/2;
block *x=first;
while (x)
{
while (x->nn>maxsize)
{
if (x->n
next) break;
// get(cur,1);
}
else
{
spilt(x,(x->n)>>1);
if (cur.ll==x&&cur.n>cur.ll->n)
{
cur.n-=cur.ll->n;
cur.ll=cur.ll->next;
}
// get(cur,1);
}
}
x=x->next;
}
}
void delet(int k)
{
if (!k) return;
if (cur.n)
{
spilt(cur.ll,cur.n);
cur.ll=cur.ll->next; cur.n=0;
}
while (k>cur.ll->n)
{
del(cur.ll);
k-=cur.ll->n;
cur.ll=cur.ll->next;
// cur.n=0;
}
if (k==cur.ll->n)
{
cur.ll->n=0;
}
else
{
spilt (cur.ll,k);
delet(k);
}
balance();
}
void insert(int k)
{
block *l=newblock();*l=block();
block *r=l;
int maxsize=min(MAXN,(int)sqrt(tot));
for (int i=1;i< =k;i++) { char c; for (scanf("%c",&c);(c<32)||(c>126)||(c=='\n');scanf("%c",&c));
if (r->n>maxsize)
{
block *tmp=r;
r=newblock();*r=block();link(tmp,r);
}
r->a[++r->n]=c;
}
if (cur.n)
{
spilt(cur.ll,cur.n);
block *tmp=cur.ll->next;
link(cur.ll,l),link(r,tmp);
}
else
{
link(cur.ll->pre,l),link(r,cur.ll),cur.ll=l;
if (first->pre) first=l;
}
balance();
}
int main()
{
first=newblock();cur.ll=first;
int t;scanf("%d",&t);
while (t--)
{
char s[10];
scanf("%s",s);
int k;
switch(s[0])
{
case'M':scanf("%d",&k);cur.move(k);break;
case'I':scanf("%d",&k);tot+=k;insert(k);break;
case'D':scanf("%d",&k);tot-=k;delet(k);break;
case'G':scanf("%d",&k);get(cur,k);printf("\n");break;
case'P':cur.pre();break;
case'N':cur.next();break;
}
// get(cursor(),tot);cout<