A. 三个师妹之出题
Description
这一次,那几个师妹给sharp出了一个题目:给定一个正整数N,求1/X+1/Y= 1/N的所有正整数解.sharp哈哈笑了两声,很简单的题目嘛....但是他一听数据范围就傻眼了,N最大可能是999999999!!!聪明的你能帮帮可怜的sharp吗?好让他不那么丢脸.
Input
第一行输入一个正整数M,下面有M行,每一行都是一个正整数N.
Output
输出共M行,每行都是方程解的个数.
Sample Input
2 1 2
Sample Output
1 3
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
long long a[20],b[20];
long long gs;
int main()
{
long long n,i,j,k,x,z,ans;
scanf("%lld",&x);
for(k=1;k<=x;k++)
{
scanf("%lld",&n);
z=n;
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
if(n<=3)
{
gs=1;
a[0]=n;
b[0]=1;
}
else
{
gs=0;
i=2;
while(i*i<=n)
{
while(n%i==0)
{
b[gs]++;
n/=i;
}
if(b[gs]>0)
{
a[gs]=i;
gs++;
}
i++;
}
if(n>1)
{
a[gs]=n;
b[gs]=1;
gs++;
}
}
if(z<2)
{
cout<<1<<endl;
}
else
{
ans=1;
for(i=0;i<gs;i++)
{
ans*=2*b[i]+1;
}
cout<<ans<<endl;
}
}
return 0;
}
B. 整数分解
Description
根据数论的有关理论可知,任何大于1的正整数都可唯一地表示为形如(P1^N1)*(P2^N2)*…(Pm^Nm)的形式。请你编程序实现。
Input
输入:第一行是测试数据的组数N(N小于10000),接着是N行正整数,每行一个,每个正整数不超过32767。
Output
输出:形式是M=(P1^N1)*(P2^N2)*…(Pm^Nm)。
说明:(a)如果幂的值为1,则不用写括号和1次幂;如:15=3*5。
(b)如果N是素数,也不用写括号和1次幂;如:7=7。
(c)如果因子只有一个,也不用写括号;如:27=3^3。
Sample Input
2 25608 24027
Sample Output
25608=(2^3)*3*11*97 24027=3*8009
#include<bits/stdc++.h>
using namespace std;
struct jg
{
int p,m;
};
jg a[21];
bool ss(int x);
int main()
{
int n,i,k,x,t,c;
cin>>n;
for(k=1;k<=n;k++)
{
for(i=1;i<=20;i++)
{
a[i].m=0;
a[i].p=0;
}
t=0;
scanf("%d",&x);
cout<<x<<'=';
if(x==1)
{
cout<<1<<'^'<<0<<endl;
continue;
}
c=x;
for(i=2;i<=x;i++)
{
if(x%i==0)
{
t++;
}
while(x%i==0&&x!=0)
{
a[t].p=i;
a[t].m++;
x/=i;
}
}
if(ss(c))
{
cout<<c<<endl;
}
else
{
if(a[2].m==0&&a[2].p==0)
{
cout<<a[1].p<<'^'<<a[1].m<<endl;
}
else
{
for(i=1;i<t;i++)
{
if(a[i].m==1)
{
cout<<a[i].p<<'*';
}
else
{
cout<<'('<<a[i].p<<'^'<<a[i].m<<")*";
}
}
if(a[t].m==1)
{
cout<<a[t].p<<endl;
}
else
{
cout<<'('<<a[t].p<<'^'<<a[t].m<<')'<<endl;
}
}
}
}
return 0;
}
bool ss(int x)
{
int i;
if(x==2)
{
return true;
}
if(x<3)
{
return false;
}
for(i=2;i<=sqrt(x);i++)
{
if(x%i==0)
{
return false;
}
}
return true;
}
C. 找新朋友
Description
新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。
Input
输入:第一行是测试数据的组数CN(Case number,1<cn<10000),接着有CN行正整数N(1<n<32768),表示会员人数。
Output
输出:对于每一个N,输出一行新朋友的人数,这样共有CN行输出。
Sample Input
2 25608 24027
Sample Output
7680 16016
#include<bits/stdc++.h>
using namespace std;
long long a[20],b[20];
long long gs;
int Aoligei(int x,int y);
int main()
{
long long n,i,j,k,x,z,ans;
scanf("%lld",&x);
for(k=1;k<=x;k++)
{
scanf("%lld",&n);
z=n;
ans=1;
for(i=2;i<=n;i++)
{
gs=0;
while(n%i==0)
{
n/=i;
gs++;
}
if(gs!=0)
{
ans*=Aoligei(i,gs-1)*(i-1);
}
}
cout<<ans<<endl;
}
return 0;
}
int Aoligei(int x,int y)
{
int i,z;
z=1;
for(i=1;i<=y;i++)
{
z*=x;
}
return z;
}
D. 小学生都会算的A+B问题
Description
大家都知道OJ上的最简单的题目就是A+B了,今天我们还是做这个A+B,不过这个数非常大,两个加数的位数不超过100000位,请你写个程序试试吧。
Input
输入有两行,每行一个正整数。
Output
输出只有一行,即两个正整数的和。
Sample Input
12345 67890123
Sample Output
67902468
//大家都知道OJ上的最简单的题目就是A+B了,今天我们还是做这个A+B,不过这个数非常大,两个加数的位数不超过100000位,请你写个程序试试吧。
#include <bits/stdc++.h>
using namespace std;
string sGetAB(string sA,string sB);//将两个string按数字加法的方式相加
void vOut(string sAB);//输出最后相加得到的值(string)
string sValid(string sC);//判断加法的值是否合法,前面可能会有多补的 '0'
int main(){
string sA,sB,sAB;
while (cin>>sA>>sB){
sAB= sGetAB(sA,sB);
sAB= sValid(sAB);
vOut(sAB);
}
return 0;
}
string sGetAB(string sA,string sB){
int nSum,nCarry;//nSum用来记录一位加法的结果,nCarry用来记录进位
string sRet; //用来相加的存放结果
int nLenA,nLenB,nLenAB;//用来记录三个string字符的长度
string sTemp; //中间变量
nLenA=sA.size();
nLenB=sB.size();
if(nLenA>nLenB){//A的长度大于B时
sTemp.resize(nLenA-nLenB,'0'); // 提前将sA和sB位数的差值赋为0
sB=sTemp+sB; //因为sB是短的那个,先给它的前面补上0
nLenAB=nLenA;
}else{//同理,当情况为A的长度小于B时,相等的时候,补上的0的个数是0个
sTemp.resize(nLenB-nLenA,'0');
sA=sTemp+sA;
nLenAB=nLenB;
}
sRet.resize(nLenAB,'0');//先给相加的结果值初始化为与sA和sB等长的 0
nCarry=0;//进位初始化0
for (int i = nLenAB-1; i >= 0 ; i--) {
nSum=(sA[i]-'0')+(sB[i]-'0')+nCarry; //从最低位开始加,nCarry是进位
sRet[i]=(char)(nSum%10+'0');//位上只能是 '0'到'9' 所以要 %10 ,并且加上'0'的ascii码值,最后再用char转换为对应的字符
nCarry=nSum/10;//记录下进位,在做下一次的位加法时,一并加上
}
if (nCarry==1){//代表最高位加完后,产生了进位,手动再在前面给他加上1位的'1'
sRet='1'+sRet;
}
return sRet;
}
string sValid(string sC){
string sRet;
int i=0;
while(i<sC.size()&&sC[i]=='0'){ //从左到右遍历,即从高位到低位遍历,记录前面多了几个 '0',后面要去除掉
i++;
}
if (i==sC.size()){
sRet='0'; //这里是当结果全是0的时候,不能把0全部摒弃,手动给结果赋一个'0'
}else{
sRet=sC.substr(i,sC.size()-i); //有多余的'0',只取后面的非'0'部分 ,从i这个位置开始取,取的长度为 sC.size()-i
}
return sRet;
}
void vOut(string sAB){ //打印最后的结果
cout<<sAB<<endl;
}
E. 幂运算精确值计算问题
Description
输入两个不超过10000的正整数a、n正整数n,输出a^n的精确结果。
Input
本问题有多组测试数据,对于每一组测试数据,只有一行,每行有用空格隔开的两个正整数。
Output
对于每一组测试数据,输出只有一行,即计算的结果。
Sample Input
2 3 91 37
Sample Output
8 3051627471597949451463369059654147285577479747909625754790616546501477931
//幂运算精确值计算问题
//输入两个不超过10000的正整数a、n正整数n,输出a^n的精确结果。
//最大值是 10000 的 10000 次方,也就是 10**(4*10000)=10 **(40000),所以最大是40001位
#include <bits/stdc++.h>
using namespace std;
#define MAX 40002 //由上面可得MAX的值,正好是40001位,因为下面j可能会比最大的实际情况40001多1位,尽管不会访问nBits[40001](从0开始,也就是第40002位),但设置为40002也是合理的
int nBits[MAX];//用数组来存储最后的结果值
int nBitsNum;//最后结果值的位数
void vInit();
void vPower(int nA,int nN);
void vOut(int nPos);
int main(){
int nA,nN;
while(cin>>nA>>nN){
if (nA==1){// 1的任何次幂都是1,所以直接输出
cout<<"1"<<endl;
}else{ //其余的正常情况如下
vInit();
vPower(nA,nN);
vOut(nBitsNum);
}
}
return 0;
}
void vInit(){
nBitsNum=1;//先初始化,结果至少有1位
}
void vPower(int nA,int nN){
int nCarry,nTemp;
int i,j;
nBits[0]=1;//先将最低位赋为1,不然得不到第一次乘的值,第一步是要将nA与最低位相乘的
for ( i = 1; i <= nN; i++) { //因为要乘nN次,这里从1开始
nCarry=0;
j=0;//j每次都从0开始,是因为做乘法每次从最低位开始的
while (true){
if (j<nBitsNum){//判断此时的j是否超过了nBitsNum,如果等于或者大于,则要去else里判断是否需要进位 ,为什么是j<nBitsNum?,继续看下面的分析
nTemp=nBits[j]*nA+nCarry;//正常的乘法与加上前一次的进位
nBits[j]=nTemp%10;//每位只能是'0'-'9',所以要取余
nCarry=nTemp/10;//记录下进位,在下次运算时加上
}else{
if (nCarry==0){//如果没有进位,正常结束本次的乘法
break;
}
nBits[j]=nCarry%10;//否则继续进位
nCarry=nCarry/10;
}
j++;//处理完本位,继续往前加位数
}
nBitsNum=j;//每次乘法结束后更新nBitsNum的值,nBitsNum每次比实际上用到的j会大1,因为在break出来本次循环的上次循环中执行过 j++
}
}
void vOut(int nPos){
for (int i = nPos-1; i >= 0; i--) { //因为nPos==nBitsNum,而每次比实际上用到的j会大1,所以是nPos-1
cout<<nBits[i];
}
cout<<endl;
}
G. 多项式的和
Description
This time, you are supposed to find A+B where A and B are two polynomials.
这一次你的任务是求解A+B,这里的A和B是两个多项式
Input
Each input file contains multiple test case. Each case occupies 2 lines, and each line contains the information of a polynomial: K N1 aN1 N2 aN2 ... NK aNK, where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1, 2, ..., K) are the exponents and coefficients, respectively. It is given that 1 <= K <= 10,0 <= NK < ... < N2 < N1 <=1000.
每个输入文件包含多组测试数据,每组测试数据有2行,每行数据是一个多项式的信息:K N1 aN1 N2 aN2 … NK aNK,其中K是非零整数,表示多项式的项数,Ni和aNi(i=1,2,…,K))表示每一项的幂和系数,K和NK符合1 <= K <= 10,0 <= NK < ... < N2 < N1 <=1000。
Output
For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1 decimal place.
对于每一组测试数据,输出只有一行,即两个多项式的和,输出的格式和输入一样,输出行的末尾没有多余的空格,输出保留一位小数。
Sample Input
2 1 2.4 0 3.2 2 2 1.5 1 0.5
Sample Output
3 2 1.5 1 2.9 0 3.2
#include <math.h>
#include <stdio.h>
using namespace std;
#define MAX 1001
#define EPS 0.05
void Input();
void Clear();
void Add();
void Output();
double a[MAX],b[MAX],c[MAX];//数组a和b是分别用来记录这两组输入的多项式,c是用来记录相加的结果的
int n,k;
int main(){
while(1== scanf("%d",&k)){
Clear();
Input();
Add();
Output();
}
return 0;
}
void Clear(){
int i;
n=0;
for (i = 0; i < MAX; i++) {
a[i]=0.0;
b[i]=0.0;
c[i]=0.0;
}
}
void Input(){//输入这两行多项式
int i,e;
double temp;
for (i = 0; i <k; i++) {
scanf("%d",&e);
scanf("%lf",&a[e]);
}
scanf("%d",&k);
for (i = 0; i <k; i++) {
scanf("%d",&e);
scanf("%lf",&b[e]);
}
}
void Add(){
int i;
for (i=0;i<MAX;i++){
c[i]=a[i]+b[i];
}
}
void Output(){
int i;
for (i=MAX-1;i>=0;i--){
if(fabs(c[i])>=EPS){//这道题的重点就是不能直接判断 double类型的值 == 0 ,要设定一个精度EPS,小于这个精度EPS的值都可以认为就是0
n++;
}
}
if(0==n){
printf("0\n");
}else{
printf("%d",n);
for (i=MAX-1;i>=0;i--){
if(fabs(c[i]>=EPS)){
printf(" %d %.1lf",i,c[i]);
}
}
printf("\n");
}
}
I. 不一样的S型方阵
Description
同学们都知道大学英语四、六级考试的座位是按照以列为主的S型安排的,今天我们要求输出另外一种S型数字方阵,例如6阶和7阶的图形如Sample所示。你现在的任务是编个程序对于输入的整数N,输出相应的方阵。
Input
本问题有多组测试数据,每组一个整数N。(0<N<=30)
Output
对于每组测试数据,输出一个方阵,每个数字场宽为4。每组最后一行由4N个“=”作为结束行。
Sample Input
6 7
#include <stdio.h>
#include <memory.h>
using namespace std;
#define MAX 31
int n;
int a[MAX][MAX];
void Init();
void Order();
void vOut();
int main()
{
while(1==scanf("%d",&n))
{
Init();
Order();
vOut();
}
return 0;
}
void Init()
{
memset(a,0,sizeof(a));
}
void Order()
{
int i,j,dig;
dig=1;
i=1;
j=n;
a[i][j]=dig;
a[i][--j]=++dig;
a[++i][++j]=++dig;
int flag=0;
int sum=n*(n+1)/2;
while(dig<sum)
{
if(i==1)
{
if(a[i+1][j+1]!=0)
{
a[i][--j]=++dig;
flag=1; //从上往下
}
else
{
a[++i][++j]=++dig;
flag=1; //从上往下
}
}
else if(j==n)
{
if(a[i-1][j-1]!=0)
{
a[++i][j]=++dig;
flag=2; //从下往上
}
else
{
a[--i][--j]=++dig;
flag=2; //从下往上
}
}
if(flag==1)
{
a[++i][++j]=++dig;
}
else if(flag==2)
{
a[--i][--j]=++dig;
}
}
sum=n*n;
while(dig<=sum)
{
if(j==1)
{
if(a[i+1][j+1]!=0)
{
a[++i][j]=++dig;
flag=1; //从上往下
}
else
{
a[++i][++j]=++dig;
flag=1; //从上往下
}
}
else if(i==n)
{
if(a[i-1][j-1]!=0)
{
a[i][--j]=++dig;
flag=2; //从下往上
}
else
{
a[--i][--j]=++dig;
flag=2; //从下往上
}
}
if(flag==1)
{
a[++i][++j]=++dig;
}
else if(flag==2)
{
a[--i][--j]=++dig;
}
}
}
void vOut()
{
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
for(i=1;i<=n;i++)
{
printf("====");
}
printf("\n");
}
J. 有趣的箭头
Description
今天你的任务是编程序画箭头图案,箭头一共有四个方向,分别用大写字母L表示朝左,R表示朝右,U表示朝上以及D表示朝下,对于给定的正整数n(n<=100),箭头图案的大小是长和宽各是4n-1,图案中空余地方用空格填充,用来表示箭头部分用给定的字符填充。
如下所示分别是n为2、3、4、5时的星号箭头:
如下所示分别是其他字符和不同方向的箭头图案:
Input
本问题有多组测试数据,每组测试数据只有一行,分别是用空格隔开的一个正整数n和两个字符,第一个字符表示朝向,一定是L、R、U、D之一,后一个字符是填充的字符。
Output
对于每一组测试数据,输出符合要求的箭头图案。
Sample Input
5 R $
Sample Output
$ $$ $$$ $$$$ $$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$ $$$$ $$$ $$ $
#include <bits/stdc++.h>
using namespace std;
int n,m;
char s[1005][1005];
int main()
{
char x,y;
while(~scanf("%d %c %c",&n,&x,&y))
{
int m=(2*n-1)+2*n;
for(int i=1;i<=2*n-1;i++)
{
for(int j=1;j<=m;j++)
{
if(j<=n||j>n+2*n-1)s[i][j]=' ';
else s[i][j]=y;
}
}
for(int i=2*n;i<=4*n-1;i++)
{
for(int j=1;j<=m;j++)
{
if(j<(i-2*n+1)||j>m-(i-2*n+1)+1)s[i][j]=' ';
else s[i][j]=y;
}
}
if(x=='R')
{
for(int i=1;i<=m;i++)
{
for(int j=1;j<=4*n-1;j++)
putchar(s[j][i]);
puts("");
}
}
else if(x=='L')
{
for(int i=1;i<=m;i++)
{
for(int j=4*n-1;j>=1;j--)
putchar(s[j][i]);
puts("");
}
}
else if(x=='D')
{
for(int i=1;i<=4*n-1;i++)
{
for(int j=1;j<=m;j++)
putchar(s[i][j]);
puts("");
}
}
else
{
for(int i=4*n-1;i>=1;i--)
{
for(int j=1;j<=m;j++)
putchar(s[i][j]);
puts("");
}
}
}
return 0;
}