目录
A 1008 Elevator
思路:
划水题~~
注意上楼下楼时间不一样就行了
**#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn=100010;
int a[maxn];
int main()
{
int n,i,sum=0;
cin>>n;
a[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>a[i-1])
{
sum+=(a[i]-a[i-1])*6+5;
}
else
{
sum+=(a[i-1]-a[i])*4+5;
}
}
cout<<sum;
return 0;
}
A 1049 Counting Ones
思路:
(1)记n的各个位从低到高分别为,第1位、第2位、第3位…
分别考虑各个位出现1时满足范围的数有多少个
(2)规律:
设当前处理至第k位,记left为第k位左边高位表示的数,now为第k位的数,right为右边低位表示的数,a为righ的位数
若now=0,则ans+=lefta;
若now=1,则ans+=lefta+right+1;
若now>1,则ans+=(left+1)*a;
具体规律推算,可以找一个例子自己推推
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n,a=1,ans=0;
int left,now,right;
cin>>n;
while(n/a!=0)
{
left=n/(a*10);
now=n/a%10;
right=n%a;
if(now==0)
ans+=left*a;
else if(now==1)
ans+=left*a+right+1;
else
ans+=(left+1)*a;
a*=10;
}
cout<<ans;
return 0;
}
A 1081 Rational Sum
思路:
这题还是得细心,有几个注意点
(1)两个分母相乘,可达到long long,所以数据取long long型
(2)必须在每一步加法后都进行约分,如果全部加完再约分,可能会溢出
(3)格式问题:带分数的整数和分数之间有一个空格
此题涉及的运算都可用函数模板:
1)求最大公约数
long long gcd(long long a,long long b)
{
return b==0?a:gcd(b,a%b);
}
2)分数化简
fraction reduction(fraction result)
{
if(result.down<0)//分母为负数,分子分母同时乘-1
{
result.up=-result.up;
result.down=-result.down;
}
if(result.up==0)
{
result.down=1;
}
else
{
int d=gcd(abs(result.up),abs(result.down));
result.up/=d;
result.down/=d;
}
return result;
}
3)分数加法
fraction add(fraction f1,fraction f2)
{
fraction result;
result.up=f1.up*f2.down+f2.up*f1.down;
result.down=f1.down*f2.down;
return reduction(result);
}
4)分数输出
void showresult(fraction r)
{
reduction(r);
if(r.down==1)
cout<<r.up;
else if(abs(r.up)>r.down)
cout<<r.up/r.down<<" "<<abs(r.up)%r.down<<"/"<<r.down;//负号在r.up/r.down已输出
else
cout<<r.up<<"/"<<r.down;
}
下面就是完整代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
//const int maxn=100010;
struct fraction
{
long long up,down;
};
//求最大公约数
long long gcd(long long a,long long b)
{
return b==0?a:gcd(b,a%b);
}
//分数化简
fraction reduction(fraction result)
{
if(result.down<0)//分母为负数,分子分母同时乘-1
{
result.up=-result.up;
result.down=-result.down;
}
if(result.up==0)
{
result.down=1;
}
else
{
int d=gcd(abs(result.up),abs(result.down));
result.up/=d;
result.down/=d;
}
return result;
}
//分数加法
fraction add(fraction f1,fraction f2)
{
fraction result;
result.up=f1.up*f2.down+f2.up*f1.down;
result.down=f1.down*f2.down;
return reduction(result);
}
//输出分数
void showresult(fraction r)
{
reduction(r);
if(r.down==1)
cout<<r.up;
else if(abs(r.up)>r.down)
cout<<r.up/r.down<<" "<<abs(r.up)%r.down<<"/"<<r.down;//负号在r.up/r.down已输出
else
cout<<r.up<<"/"<<r.down;
}
int main()
{
int n;
cin>>n;
fraction sum,temp;
sum.up=0;
sum.down=1;
for(int i=0;i<n;i++)
{
scanf("%lld/%lld",&temp.up,&temp.down);
sum=add(sum,temp);
}
showresult(sum);
return 0;
}
A 1015 Reversible Primes
思路:
几个常用模板直接记下来,套用即可
1)素数判断
bool isprime(int n)
{
if(n<=1)
return false;
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
2)进制转换
int z[40]
int k=0;
do
{
z[k++]=n%d;
n=n/d;
}while(n!=0);
完整代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<math.h>
using namespace std;
const int maxn=100010;
int z[maxn];
bool isprime(int n)
{
if(n<=1)
return false;
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
int main()
{
int n,d;
while(~scanf("%d",&n))
{
if(n<0)
break;
scanf("%d",&d);
if(!isprime(n))
printf("No\n");
else
{
int k=0;
do
{
z[k++]=n%d;
n=n/d;
}while(n!=0);
for(int i=0;i<k;i++)
n=n*d+z[i];
if(isprime(n))
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}
A 1078 Hashing
思路:
(1)判断素数,找出第一个比msize大的素数
(2)hash应用,判断冲突
(3)冲突解决:如果step从0~msize-1进行枚举仍然找不到位置,那么对于step大于等于msize来说也不可能找到位置(证明略)
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<math.h>
using namespace std;
const int maxn=100010;
bool hashtable[maxn]={false};
bool isprime(int n)
{
if(n<=1)
return false;
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
int main()
{
int msize,n,temp;
cin>>msize>>n;
while(isprime(msize)==false)
{
msize++;
}
for(int i=0;i<n;i++)
{
scanf("%d",&temp);
int k=temp%msize;
if(hashtable[k]==false)
{
hashtable[k]=true;
if(i==0)
printf("%d",k);
else
printf(" %d",k);
}
else
{
int step;
for(step=1;step<msize;step++)
{
int m=(temp+step*step)%msize;
if(hashtable[m]==false)
{
hashtable[m]=true;
printf(" %d",m);
break;//这个不能忘,不然出现死循环,最后一个测试点运行超时
}
}
if(step>=msize)
{
if(i>0)
printf(" ");
printf("-");
}
}
}
return 0;
}
A 1096 Consecutive Factors
思路:
这题的一个技巧点就是,寻找的连续整数其开头的第一个整数肯定不会超过
n
\sqrt{n}
n,这样可以缩短遍历的范围
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<math.h>
using namespace std;
//const int maxn=100010;
int main()
{
int n;;
cin>>n;
int sqr=(int)sqrt(1.0*n);
int ansi=0,anslen=0;
for(int i=2;i<=sqr;i++)
{
int temp=1;
for(int j=i;j<n;j++)
{
temp*=j;
if(n%temp!=0)
break;
if(j-i+1>anslen)
{
ansi=i;
anslen=j-i+1;
}
}
}
if(anslen==0)
cout<<"1"<<endl<<n;
else
{
cout<<anslen<<endl;
for(int i=0;i<anslen;i++)
{
cout<<ansi+i;
if(i<anslen-1)
cout<<"*";
}
}
return 0;
}
A 1059 Prime Factors
思路:
对于一个正整数n来说,如果它存在【2,n】范围内的质因子,要么这些质因子全部小于等于
n
\sqrt{n}
n,要么只存在一个大于
n
\sqrt{n}
n的质因子。
(1)素数表的打印
(2)质因子分解
//打印素数表,模板
bool isprime(int n)
{
if(n<=1)
return false;
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
int prime[maxn];
int num=0;
void Find_Prime()
{
for(int i=1;i<maxn;i++)
{
if(isprime(i))
prime[num++]=i;
}
}
完整代码:
#include <cstring>
#include<cstdio>
#include<algorithm>
#include<math.h>
#include <iostream>
using namespace std;
const int maxn=100010;
struct factor
{
int x;
int cnt;
}fac[11];
bool isprime(int n)
{
if(n<=1)
return false;
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
int prime[maxn];
int num=0;
void Find_Prime()
{
for(int i=1;i<maxn;i++)
{
if(isprime(i))
prime[num++]=i;
}
}
int main()
{
Find_Prime();
int n,count=0;
scanf("%d",&n);
if(n==1)
printf("1=1");//特判1的情况,否则,无法输出1的结果
else
{
printf("%d=",n);
int sqr=(int)sqrt(1.0*n);
for(int i=0;prime[i]<=sqr;i++)
{
if(n%prime[i]==0)
{
fac[count].x=prime[i];//记录质因子
fac[count].cnt=0;
while(n%prime[i]==0)//计算个数
{
fac[count].cnt++;
n/=prime[i];
}
count++;
}
if(n==1)
break;//及时退出循环,1与任何大于1的数取余都是1
}
if(n!=1)//如果无法被根号n以内的质因子除尽
{
fac[count].x=n;//那么一定有一个大于根号n的质因子
fac[count++].cnt=1;
}
for(int i=0;i<count;i++)
{
if(i>0)
printf("*");
printf("%d",fac[i].x);
if(fac[i].cnt>1)
{
printf("^%d",fac[i].cnt);
}
}
}
return 0;
}
A Have Fun with Numbers
思路:
(1)大整数乘法,高位数整数*低位数整数
(2)hash应用
该题又涉及函数模板(大整数乘法)
1)大整数结构体
struct bign
{
int d[22];
int len;
bign()
{
memset(d,0,sizeof(d));
len=0;
}
};
bign change(char str[])
{
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++)
{
a.d[i]=str[a.len-1-i]-'0';
}
return a;
}
2)大整数乘法
bign multi(bign a,int b)
{
bign c;
int carry=0;
for(int i=0;i<a.len;i++)
{
int temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
while(carry!=0)//和加法不一样,乘法的进位可能不止一位
{
c.d[c.len++]=carry%10;
carry/=10;
}
return c;
}
完整代码
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<math.h>
using namespace std;
//const int maxn=100010;
struct bign
{
int d[22];
int len;
bign()
{
memset(d,0,sizeof(d));
len=0;
}
};
bign change(char str[])
{
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++)
{
a.d[i]=str[a.len-1-i]-'0';
}
return a;
}
bign multi(bign a,int b)
{
bign c;
int carry=0;
for(int i=0;i<a.len;i++)
{
int temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
while(carry!=0)//和加法不一样,乘法的进位可能不止一位
{
c.d[c.len++]=carry%10;
carry/=10;
}
return c;
}
int main()
{
char str[22];;
cin>>str;
bign a=change(str);
bign mul=multi(a,2);
int i=0;
if(a.len!=mul.len)
printf("No\n");
else
{
int flag[10]={0};
for(i=0;i<a.len;i++)
{
flag[a.d[i]]++;
flag[mul.d[i]]--;
}
for(i=0;i<10;i++)
{
if(flag[i]!=0)
{
printf("No\n");
break;
}
}
if(i==10)
printf("Yes\n");
}
for(i=mul.len-1;i>=0;i--)
cout<<mul.d[i];
return 0;
}
A 1024 Palindromic Number
思路:
和上一题相比,就多了一个判断回文串的函数,也就是从数组两端开始对比。
大整数加法和乘法其实很相似
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<math.h>
using namespace std;
const int maxn=100010;
char str[maxn];
struct bign
{
int d[maxn];
int len;
bign()
{
memset(d,0,sizeof(d));
len=0;
}
};
bign change(char str[])
{
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++)
{
a.d[i]=str[a.len-1-i]-'0';
}
return a;
}
bign add(bign a,bign b)
{
bign c;
int carry=0;
for(int i=0;i<a.len||i<b.len;i++)
{
int temp=a.d[i]+b.d[i]+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
if(carry!=0)
{
c.d[c.len++]=carry;
}
return c;
}
bool judge(bign a)
{
for(int i=0;i<a.len;i++)
{
if(a.d[i]!=a.d[a.len-1-i])
return false;
}
return true;
}
void print(bign a)
{
for(int i=a.len-1;i>=0;i--)
printf("%d",a.d[i]);
printf("\n");
}
int main()
{
int n,i;
cin>>str>>n;
bign a=change(str);
for(i=0;i<n;i++)
{
if(judge(a))
break;
bign b=a;
reverse(b.d,b.d+b.len);
a=add(a,b);
}
print(a);
cout<<i;
return 0;
}