关于STL的一些学习,发现STL现在越来越重要了

背景:首先由于我不擅长STL运用,所以专门学习了一下,所以将的也会比较肤浅了点,期待您的批阅。

1)set (集合) :这是微软帮助文档中对集合(set)的解释: “描述了一个控制变长元素序列的对象(注:set中的key和value是Key类型的,而map中的key和value是一个pair结构中的两个分 量)的模板类,每一个元素包含了一个排序键(sort key)和一个值(value)。对这个序列可以进行查找、插入、删除序列中的任意一个元素,而完成这些操作的时间同这个序列中元素个数的对数成比例关 系,并且当游标指向一个已删除的元素时,删除操作无效。”
而一个经过更正的和更加实际的定义应该是:一个集合(set)是一个容器,它其中所包含 的元素的值是唯一的。这在收集一个数据的具体值的时候是有用的。集 合中的元素按一定的顺序排列,并被作为集合中的实例。如果你需要一个键/值对(pair)来存储数据,map是一个更好的选择。一个集合通过一个链表来组 织,在插入操作和删除操作上比向量(vector)快,但查找或添加末尾的元素时会有些慢。该集合里存放的数都已经排好序了,并且自动删除了一些重复的元素。

样例操作:

#include<iostream>
#include<set>
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
    set<string>s;
    set<string>::iterator it;
    s.insert("apple");
    s.insert("appla");
    s.insert("basjk");
    s.insert("appje");
    s.insert("apale");
    s.insert("aaple");
    s.insert("abple");
    s.insert("akple");
    it=s.begin();
    while(it!=s.end()){
        cout<<*it<<" "<<endl;
        it++;
    }
    return 0;
}

输入结果是:

aaple
abple
akple
apale
appje
appla
apple
basjk

vector的介绍:

构造有四种方式:

  • 无参数 - 构造一个空的vector,
  • 数量(num)和值(val) - 构造一个初始放入num个值为val的元素的Vector
  • vector(from) - 构造一个与vector from 相同的vector
  • 迭代器(start)和迭代器(end) - 构造一个初始值为[start,end)区间元素的Vector(注:半开区间).
    任意以上一种都可以。
    例如:vector<int >s(  5 ,21 ) ,这样就定义了一个包含5个21的vector;


    assign函数

    语法:
    void assign( input_iterator start, input_iterator end ); void assign( size_type num, const TYPE &val );

    assign() 函数要么将区间[start, end)的元素赋到当前vector,或者赋num个值为val的元素到vector中.这个函数将会清除掉为vector赋值以前的内容.

    at函数

    语法:
    TYPE at( size_type loc );

    at() 函数 返回当前Vector指定位置loc的元素的引用. at() 函数 比 [] 运算符更加安全, 因为它不会让你去访问到Vector内越界的元素. 例如, 考虑下面的代码:

    vector<int> v( 5, 1 ); for( int i = 0; i < 10; i++ ) { cout << "Element " << i << " is " << v[i] << endl; }
    这段代码访问了vector末尾以后的元素,这将可能导致很危险的结果.以下的代码将更加安全:
    vector<int> v( 5, 1 ); for( int i = 0; i < 10; i++ ) { cout << "Element " << i << " is " << v.at(i) << endl; }

    取代试图访问内存里非法值的作法,at() 函数能够辨别出访问是否越界并在越界的时候抛出一个异常.

  • back 函数

    语法:
    TYPE back();

    back() 函数返回当前vector最末一个元素的引用.例如:

    vector<int> v; for( int i = 0; i < 5; i++ ) { v.push_back(i); } cout << "The first element is " << v.front() << " and the last element is " << v.back() << endl;

    这段代码产生如下结果:

    The first element is 0 and the last element is 4
    相关内容: front().

    begin 函数

    语法:
    iterator begin();

    begin()函数返回一个指向当前vector起始元素的迭代器.例如,下面这段使用了一个迭代器来显示出vector中的所有元素:

    vector<int> v1( 5, 789 ); vector<int>::iterator it; for( it = v1.begin(); it != v1.end(); it++ ) cout << *it << endl;
    相关内容: end().

    capacity 函数

    语法:
    size_type capacity();

    capacity() 函数 返回当前vector在重新进行内存分配以前所能容纳的元素数量.


    clear 函数

    语法:
    void clear();

    clear()函数删除当前vector中的所有元素.


    empty 函数

    语法:
    bool empty();

    如果当前vector没有容纳任何元素,则empty()函数返回true,否则返回false.例如,以下代码清空一个vector,并按照逆序显示所有的元素:

    vector<int> v; for( int i = 0; i < 5; i++ ) { v.push_back(i); } while( !v.empty() ) { cout << v.back() << endl; v.pop_back(); }
    相关内容: size()

    end 函数

    语法:
    iterator end();

    end() 函数返回一个指向当前vector末尾元素的下一位置迭代器.注意,如果你要访问末尾元素,需要先将此迭代器自减1.

    来源:(http://blog.sina.com.cn/s/blog_66ced15f0100hu9e.html) - C++ STL Vector_老虎_晓茗_新浪博客

    相关内容: begin()


    erase 函数

    语法:
    iterator erase( iterator loc ); iterator erase( iterator start, iterator end );
    erase函数要么删作指定位置loc的元素,要么删除区间[start, end)的所有元素.返回值是指向删除的最后一个元素的下一位置的迭代器.例如:
    // 创建一个vector,置入字母表的前十个字符 vector<char> alphaVector; for( int i=0; i < 10; i++ ) alphaVector.push_back( i + 65 ); int size = alphaVector.size(); vector<char>::iterator startIterator; vector<char>::iterator tempIterator; for( int i=0; i < size; i++ ) { tartIterator = alphaVector.begin(); alphaVector.erase( startIterator ); // Display the vector for( tempIterator = alphaVector.begin(); tempIterator != alphaVector.end(); tempIterator++ ) cout << *tempIterator; cout << endl; }
    

    这段代码将会显示如下输出:

    BCDEFGHIJ CDEFGHIJ DEFGHIJ EFGHIJ FGHIJ GHIJ HIJ IJ J
    相关内容: pop_back().

    front 函数

    语法:
    TYPE front();

    front()函数返回当前vector起始元素的引用

    相关内容: back().


    get_allocator 函数

    语法:
    allocator_type get_allocator();

    get_allocator() 函数返回当前vector的内存分配器.


    insert 函数

    语法:
    iterator insert( iterator loc, const TYPE &val ); void insert( iterator loc, size_type num, const TYPE &val ); void insert( iterator loc, input_iterator start, input_iterator end );

    insert() 函数有以下三种用法:

  • 在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器,
  • 在指定位置loc前插入num个值为val的元素
  • 在指定位置loc前插入区间[start, end)的所有元素 .

举例:

//创建一个vector,置入字母表的前十个字符 vector<char> alphaVector; for( int i=0; i < 10; i++ ) alphaVector.push_back( i + 65 ); //插入四个C到vector中 vector<char>::iterator theIterator = alphaVector.begin(); alphaVector.insert( theIterator, 4, 'C' ); //显示vector的内容 for( theIterator = alphaVector.begin(); theIterator != alphaVector.end(); theIterator++ ) cout << *theIterator;

这段代码将显示:

CCCCABCDEFGHIJ

max_size 函数

语法:
size_type max_size();

max_size() 函数返回当前vector所能容纳元素数量的最大值(译注:包括可重新分配内存).


pop_back

语法:
void pop_back();

pop_back()函数删除当前vector最末的一个元素,例如:

vector<char> alphaVector; for( int i=0; i < 10; i++ ) alphaVector.push_back( i + 65 ); int size = alphaVector.size(); vector<char>::iterator theIterator; for( int i=0; i < size; i++ ) { alphaVector.pop_back(); for( theIterator = alphaVector.begin(); theIterator != alphaVector.end(); theIterator++ ) cout << *theIterator; cout << endl; }

这段代码将显示以下输出:

ABCDEFGHI ABCDEFGH ABCDEFG ABCDEF ABCDE ABCD ABC AB A
相关内容: erase().

push_back 函数

语法:
void push_back( const TYPE &val );

push_back()添加值为val的元素到当前vector末尾


rbegin 函数

语法:
reverse_iterator rbegin();

rbegin函数返回指向当前vector末尾的逆迭代器.(译注:实际指向末尾的下一位置,而其内容为末尾元素的值,详见逆代器相关内容)


rend 函数

语法:
reverse_iterator rend();

rend()函数返回指向当前vector起始位置的逆迭代器.


reserve 函数

语法:
void reserve( size_type size );

reserve()函数为当前vector预留至少共容纳size个元素的空间.(译注:实际空间可能大于size)


resize 函数

语法:
void resize( size_type size, TYPE val );

resize() 函数改变当前vector的大小为size,且对新创建的元素赋值val


size 函数

语法:
size_type size();

size() 函数返回当前vector所容纳元素的数目

相关内容: empty()


swap 函数

语法:
void swap( vector &from );

swap()函数交换当前vector与vector from的元素

  •  

HDU 1271(整数对 经典!)

题目大意:

Problem Description
             Gardon和小希玩了一个游戏,Gardon随便想了一个数A(首位不能为0),把它去掉一个 数字以后得到另外一个数B,他把A和B的和N告诉了小希,让小希猜想他原来想的数字。不过为了公平起见,如果小希回答的数虽然不是A,但同样能达到那个条 件(去掉其中的一个数字得到B,A和B之和是N),一样算小希胜利。而且小希如果能答出多个符合条件的数字,就可以得到额外的糖果。
所以现在小希希望你编写一个程序,来帮助她找到尽可能多的解。
例如,Gardon想的是A=31,B=3 告诉小希N=34,
小希除了回答31以外还可以回答27(27+7=34)所以小希可以因此而得到一个额外的糖果。
 

Input
输入包含多组数据,每组数据一行,包含一个数N(1<=N<=10^9),文件以0结尾。
 
Output

对于每个输入的N,输出所有符合要求的解(按照大小顺序排列)如果没有这样的解,输出"No solution."

题目分析:第一次,我的思路是从一半开始枚举,发现这样超时了

TLE代码:

#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
int s[1000];
inline int solve(int x){
	int k,ans,i,j;
	int c,sum,t,times=1;
	while(c){
			c/=10;
			k++;
		}
	int xx=pow(10,k-2);
	for(i=xx;i<=x;i++){
		k=0;	c=i;
		while(c){
			c/=10;
			k++;
		}
		for(j=1;j<=k;j++){
			c=i;
			sum=0;
			int w=(int)pow(10,k-j);
			if(j==1){
				sum=c%w;
			}
			if(j==k){
				sum=c/10;
			}
			if(j!=k&&j!=1){
				t=c%w;
				int p=c/w;
				p/=10;
				p=p*((int)pow(10,k-j));
				sum=p+t;
			}
			if(sum+i==x){
				s[times++]=i;
			}
		}
	}
	return times-1;
}
int main(){
	int x,t,i;
	while(scanf("%d",&x),x){
		t=solve(x);
		if(t==0)
			printf("No solution.\n");
		else{
			for(i=1;i<=t;i++)
				printf("%d ",s[i]);
			printf("\n");
		}
	}
	return 0;
}

后来看了一下解题报告,后来终于理解了,现在让我来说说这题的做法跟规律吧{^_^}

首先假设X的第k位拿走,然后加上加上X的和正好等于N!

这样的话 我们可以把X 分解成:X= a+b * 10^k +c * 10^( k+1 );  这里特别强调一下, a代表的是比第k位后面的低位数子,可能是多位,b仅仅代表一个数值,即你选择拿开的那位数,c代表的是比k位高的高位数字,例如:12345 您想拿走3的话 这时候a=45,c=12,b=3;   然后拿走之后就会组合成另一个数:Y=a + c * 10^k; 然后X+Y=2 * a + b * 10 ^k +11 * c * 10^k;

现在如果N=X+Y;他必定满足上面那种结构!所以我们考虑这种结构特征就可以了,首先上述表达式的低位是2*a 可能发生进位!

所以b的值可能是10,但是 都不影响c的值, 这个时候只需要分两种不同的b的情况,来求出a,然后验证一下 是不是等于N就可以了!

AC代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
void solve(int x,set<int> &result){
	int k,high,b2,a;
	int c,sum,b1;
	for(k=1;k<=x;k*=10){
		high=x/k;
		c=high/11;
		c*=k;
		b1=high%11;
		if((b1!=0||c!=0)&&b1<10){
			b1*=k;
			a=(x-b1-11*c)/2;
			if(2*a+b1+11*c==x)
				result.insert(a+b1+c*10);	
		}
		b2=high%11-1;
		if((b2!=0||c!=0)&&b2>=0){
			b2*=k;
			int a2=(x-b2-11*c)/2;
			if(x==2*a2+b2+11*c)
				result.insert(a2+b2+10*c);
		}
	}
}
int main(){
	int x,i;
	while(cin>>x,x){
		set<int>result;
            //set结构不仅可以排序,而且可以去除重复的
            //下次要多多学习,总结!
		solve(x,result);
		if(result.empty()){
			printf("No solution.\n");
		}
		else{
			set<int>::iterator it=result.begin();
			printf("%d",*it);
			while(++it!=result.end())
				printf(" %d",*it);
			printf("\n");
		}
	}
	return 0;
}

还有一种代码思路一样

AC代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int s[1000],times;
int cmp(int x,int y){
	return x<y;
}
int solve(int x){
	int k,high,b2,a;
	int c,sum,b1;
	times=0;
	for(k=1;k<=x;k*=10){
		high=x/k;
		c=high/11;
		c*=k;
		b1=high%11;
		if((b1!=0||c!=0)&&b1<10){
			b1*=k;
			a=(x-b1-11*c)/2;
			if(2*a+b1+11*c==x)
				s[++times]=a+b1+c*10;	
		}
		b2=high%11-1;
		if((b2!=0||c!=0)&&b2>=0){
			b2*=k;
			a=(x-b2-11*c)/2;
			if(x==2*a+b2+11*c)
				s[++times]=a+b2+10*c;
		}
	}
	return 0;
}
int main(){
	int x,t,i;
	while(scanf("%d",&x)&&x){
		solve(x);
		if(times==0){
			printf("No solution.\n");
		}
		else{
			sort(s+1,s+1+times,cmp);
			printf("%d",s[1]);
			 for(i=2;i<=times;i++){
    				if(s[i]!=s[i-1])
   				printf(" %d",s[i]);
   			}
			printf("\n");
		}
	}
	return 0;
}

题目总结:今后一定要大量深入学校STL函数!还有这题的去除重复不能忘记,同时要深刻认识本题的思路,太巧妙,强大了

HDU 1215(七夕节)

题目大意:您的编号N的因子和就是您的另一半的编号!数字N的因子就是所有比N小又能被N整除的所有正整数,如12的因子有1,2,3,4,6.输入数据的第一行是一个数字T(1<=T<=500000),它表明测试数据的组数.然后是T组测试数据,每组测试数据只有一个数字N(1<=N<=500000).

题目分析:其实是水题!一开始想复杂了,后来想想看,我们只要找i :1->sqrt(N)然后用通过N/i 找到比sqrt(N)大的满足要求的因子!

这样最坏情况下也才500000*3000最多!还是不会超时的

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int solve(int x){
	int i,j,sum=0;
	double tempt=sqrt(x);
	for(i=2;i<=tempt;i++){
		if(x%i==0){
			sum+=i;
			int t=x/i;
			if(t!=i){
				sum+=t;	
                          //是在里面判断比sqrt(N)大的因子合法与否!
			}
		}
	}
	sum+=1;
	return sum;
}
int main(){
	int cas,t,ans;
	scanf("%d",&cas);
	while(cas--){
		scanf("%d",&t);
		ans=solve(t);
		printf("%d\n",ans);
	}
	return 0;
}

 

HDU 2504(又见GCD)

题目:

有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b。若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c。

刚刚开始的时候写错了,没考虑太多,直接a/b如果不等于1 就a/b-1然后乘以b!

其实枚举就行了:

#include<iostream>
#include<cstdio>
using namespace std;
int gcd(int x,int y){
	int c;
	if(x<y){
		c=y;
		y=x%y;
		x=c;
	}
	while(y){
		c=y;
		y=x%y;
		x=c;
	}
	return x;
}
int main(){
	int a,b,c,flag,cas;
	cin>>cas;
	while(cas--){
		scanf("%d %d",&a,&b);
		for(int i=2;;i++){
			if(gcd(a,i*b)==b){
				flag=i;
				break;
			}
		}
		printf("%d\n",flag*b);
	}
	return 0;
}

总结:唉,汗颜!下次细心!UP!

HDU 1722(分蛋糕 规律性题目)

一次生日Party可能有p人或者q人参加,现准备有一个大蛋糕.问最少要将蛋糕切成多少块(每块大小不一定相等),才能使p人或者q人出席的任何一种情况,都能平均将蛋糕分食.

题目分析:p+q-gcd(p+q)

代码:

#include<iostream>
#include<cstdio>
using namespace std;
int gcd(int a,int b){
	int c;
	if(a<b){
		c=a;	a=b;
		b=c;
	}
	while(b){
		c=b;
		b=a%b;
		a=c;
	}
	return a;
}
int main(){
	int x,y;
	while(~scanf("%d %d",&x,&y)){
		printf("%d\n",x+y-gcd(x,y));
	}
	return 0;
}

 

猴子分桃(很有趣的规律题)

题目大意:老猴子辛苦了一辈子,给那群小猴子们留下了一笔巨大的财富——一大堆桃子。
老猴子决定把这些桃子分给小猴子。
第一个猴子来了,它把桃子分成五堆,五堆一样多,但还多出一个。它把剩下的一个留给老猴子,自己拿走其中的一堆。
第二个猴子来了,它把桃子分成五堆,五堆一样多,但又多出一个。它把多出的一个留给老猴子,自己拿走其中的一堆。
后来的小猴子都如此照办。最后剩下的桃子全部留给老猴子。
这里有n只小猴子,请你写个程序计算一下在开始时至少有多少个桃子,以及最后老猴子最少能得到几个桃子。

题目分析:其实题目不是很难,但是我很悲剧的是,因为学校服务器的问题,害我WA了20多次,后来都别的网站上提交,1Y就过了!

这里表示非常不淡定。。。

废话不说了让我们看题目吧:假设有X个桃子,第一次把X个桃子分成5份,恰好多了1,然后拿走一份!再这里,您应该想到借他4个不就正好5份了麽?然后每次都不是5份了麽?最后当前猴子拿走的也没多拿不是麽?举个例子说明一下吧,假设有5只猴子,第一次每份

(X-1)/5;如果我们借给他4个,每份不就是(X+4)/5吗?然后您会发现,(X+1)/5=(X-1)/5+1;每次都是如此,然后每次都能被5整除,这很显然,所以您应该懂了吧~{^_^}X=5^n-4  老猴子得到=n+(X+4)*(4/5)^n-4(您得还我的呀!对吧 嘿嘿)

代码+部分注释:

#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std;
int main(){
	long long total_num,old_num;
	int n;
	while(cin>>n,n){
		total_num=pow(5,n)-4;
		old_num = n + (total_num+4)*(pow(0.8,n))-4;
		cout<<total_num<<" "<<old_num<<endl;
	}
	return 0;
}

 

HDU 1713(相遇周期)求分数的最小公倍数!

题目分析:题目输入c1/t1 c2/t2 ,也就是速度的分数形式,转换成:c1*t2/(t1*t2),  c2*t1/( t1*t2 ); 这时候我们只需要求出分子的最小公倍数k,然后k/( t1*t2 )就是题目求的周期

代码+部分注释:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
__int64 gcd(__int64 a,__int64 b){
	__int64 c;
	if(a<b){
		c=a;	a=b;
		b=c;
	}
	while(b){
		c=b;
		b=a%b;
		a=c;
	}
	return a;
}
__int64 min_times(__int64 x1,__int64 x2){
	__int64 c=gcd(x1,x2);
	return x1*x2/c;
}
int main(){
	__int64 cas,c1,c2,t1;
	__int64 t2,p,k,m,n,h;
	cin>>cas;
	while(cas--){
		scanf("%I64d/%I64d",&c1,&t1);
                 //在这里提醒一下,用long long型的过不了!
                 //因为这个WA的好多次!
		scanf("%I64d/%I64dd",&c2,&t2);
		k=t1*t2;
		m=t2*c1;
		n=t1*c2;
		p=min_times(m,n);
		h=gcd(p,k);
		if(h==k){
			printf("%I64d\n",p/h);
		}
		else{
			printf("%I64d/%I64d\n",p/h,k/h);
		}
	}
	return 0;
}

 

HDU 2138(求素数的个数,容易超时!提醒自己)

题目分析:这里不能打表,然后要用到求素数的 优化!也就是我 前面一篇文章提到的。代码直接注释一下就可以了 还是看代码吧

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
bool prime(int x){
	if(x%2==0&&x!=2)
		return false;
         //偶数肯定不是素数!
	double k=sqrt(x);
        //切记这里一定要用k记录他的开方
        //如果写成for(int i=3;i*i<=x;i+=2)
        //就超时!
	for(int i=3;i<=k;i+=2)//枚举奇数!
		if(x%i==0)
			return false;
	return true;
}
int main(){
	int cas,n,flag,ans=0;
	while(~scanf("%d",&cas)){
		ans=0;
		while(cas--){
			scanf("%d",&n);
			if(prime(n))
				ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

ZOJ 3498(Javabeans)

题目分析:把每个盒子看成集合。有n个集合,分别有1…n个元素。具体每种集合有多少个是没意义的,因为我们可以把具有相同元素的集合同时操作,所以我们可以用集合的种类代替集合的个数。假设,每次选取k个集合。从这k个集合里拿东西,则这k个集合拿过之后还是k个不同的集合(有可能有一个成空集),所以至少还有(k-1)个不同的集合,而除这k个外还有(n-k)个不同的集合。所以拿完之后不同集合的个数至少变为了r=max(k-1,n-k)。考虑当n是偶数时当k=n/2时,r取最小值,max(k-1,n-k)=n/2,当n为奇数时,k=(n+1)/2,r取最小值max(k-1,n-k)=(n-1)/2。这个最小值是剩余集合数的一个下界。

其实这个下界是可以达到的:

n是偶数时,从元素个数不少于n/2的全部集合里都拿n/2个,则,剩余集合元素个数变为了1,2……n/2,问题规模缩小了一半。

n是奇数时,从元素个数不少于(n+1)/2的集合里都拿(n+1)/2个,则剩余集合元素个数变为了1,2,…(n-1)/2,问题规模也缩小了一半。

而在c语言中,除以2是下取整的,所以无论n为奇数还是偶数,一次操作之后集合个数至少变成了n/2,并且有办法可以达到这个最小值。

于是,最少拿的次数就是每次把n不断除以2,除到0为止。即n2进制表示

代码:

#include<iostream>
#include<cstdio>
typedef long long ll;
int main(){
	ll n,ans,times;
	scanf("%lld",×);
	while(times--){
		scanf("%lld",&n);
		ans=0;
		while(n){
			ans++;
			n/=2;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

 

HDU 1492(求一个数的倍数)

题目大意:

首先 2,3,5,7是互质的!可以把 N 写成 (2^a)*(3^b)*(5^c)*(7^d)   (a,b,c,d >= 0)!

每次从a ,b,c,d中选出一组数就是一个因数

举例说明一下:12=2^2*3

         因为1也是他的倍数!2能够构成的倍数有(1,1*2,2*2)    3构成的倍数有(1,1*3)

     也就是把(a+1)*(b+1)*....(n+1)就是能整除他的个数

   代码+部分注释:

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int pri[5];
long long times[5];
int pricount(long long num){
	pri[1]=2;
  	pri[2]=3;
	pri[3]=5;
	pri[4]=7;
	memset(times,0,sizeof(times));
	long long i;
	for(i=1;i<=4;i++){
		while(num%pri[i]==0){
			times[i]++;
			num/=pri[i];
		}
	}
	return 0;
}

int main(){
	long long n,sum;
	long long i;
	while(cin>>n,n){
		sum=1;
		pricount(n);
		for(i=1;i<=4;i++)
			sum=sum*(times[i]+1);
                     //注意要+1,上面已经分析了!
		cout<<sum<<endl;
	}
}