总结
01、高斯日记 手算/excel/编程(枚举,模拟翻日历)
坑点:第一天
02、马虎的算式 枚举+check
03、第39级台阶 普通走台阶的变体–递归思维
***04、黄金连分数 黄金分割与斐波那契数列,大数加法,大数除法(减法)
n取多少,100位的小数才稳定呢
05、前缀判断 C语言字符出处理,比对+偏移
06、三部排序 快速排序的变体 单指针 双指针 三指针
07、错误票据 排序+遍历
*08、翻硬币 找规律
***09、带分数 全排列+字符串切割
全排列+字符转整数(不能用atoi函数)——坑很大
10、连号区间数 简单枚举
1.高斯日记(出生当天记为第一天)
日期API和excel无法处理和计算1970年以前的日期。
解法1、excel
解法2、简单枚举
可测试题目所给的数据,得到出生那天是否算第一天。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
using namespace std;
bool isleaperyear(int y){
return ((y%4==0)&&(y%100!=0))||(y%400==0);
}
int main(){
int y=1777;
int m=4;
int d=30;
for(int i=0;i<8112;i++ ){
d++;
if(m==12&&d==32){
y++;
m=1;
d=1;
continue;
}
if((m==1||m==3||m==5||m==7||m==8||m==10||m==12)&&d==32)
{
m++;
d=1;
continue;
}
if((m==4||m==6||m==9||m==11)&&d==31)
{
m++;
d=1;
continue;
}
if(m==2&&isleaperyear(y)&&d==30){
m++;
d=1;
continue;
}
if(m==2&&!isleaperyear(y)&&d==29){
m++;
d=1;
continue;
}
}
printf("%d-%d-%d",y,m,d);
return 0;
}
2.马虎的算式
枚举
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
using namespace std;
int main(){
int count=0;
for(int a=1;a<10;a++){
for(int b=1;b<10;b++){
if(b!=a)
for(int c=1;c<10;c++){
if(c!=a&&c!=b)
for(int d=1;d<10;d++){
if(d!=a&&d!=b&&d!=c)
for(int e=1;e<10;e++){
if(e!=a&&e!=b&&e!=c&&e!=d){
if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e))
count++;
}
}
}
}
}
}
printf("%d",count) ;
return 0;
}
3.第39级台阶
背dfs的模板
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
using namespace std;
int ans;
//n 剩下的阶梯数
//step 已经走的步数
void dfs(int n,int step){
if(n<0) return;//边界条件
if(n==0&&step%2==0) ans++;
dfs(n-1,step+1);//递归
dfs(n-2,step+1);
}
int main(){
dfs(39,0);
printf("%d",ans);
return 0;
}
4、黄金连分数(秒出大数的加法)
(1)转为求斐波那契数列的n和n+1项
(2)n取多少?再增加n,小数点后的101位没有发生变化。
(3)不能用c语言定义的整数型直接运算,而要手工地写大数加法和除法(减法)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
#include<sstream>
#include<iostream>
using namespace std;
int n=400;//稳定
string add(string a,string b){
a=a.substr(a.find_first_not_of('0'));//删掉前面的0
b=b.substr(b.find_first_not_of('0'));//删掉前面的0
long long lenA=a.length();
long long lenB=b.length();
long long len=max(lenA,lenB)+10;
//翻转,便于从低位逐步求和
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
string ans(len,'0');//初始化ans为len长,全部字符为0
//把a拷贝到ans中
for(int i=0;i<lenA;i++){
ans[i]=a[i];
}
int tmp=0; //tmp是上一位相加后的进位
for(int j=0;j<len;j++){
if(j<b.length())
tmp+=(ans[j]-'0')+(b[j]-'0');//假设为18
else
tmp+=(ans[j]-'0');
ans[j]=tmp%10+'0';//取个位 8
tmp/=10;//取十位 1
}
reverse(ans.begin(),ans.end());
ans=ans.substr(ans.find_first_not_of('0'));//删掉前面的0
return ans;
}
int cmp(string a,string b){
unsigned long i1=a.find_first_not_of('0');
unsigned long i2=b.find_first_not_of('0');
if(i1==string::npos) a='0';
else a.substr(i1);
if(i2==string::npos) b='0';
else b.substr(i2);
if(a.length()>b.length()) return 1;
else if(a.length()<b.length()) return -1;
else{//长度相等
if(a<b) return -1;
if(a>b) return 1;
else return 0;
}
}
//此处a一定大于等于b
string subtract(string a,string b){
//完整的减法里面,a可以小于b,这时结果为负数,交换a,b进行下面的代码
//1.翻转
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
//2.按位做减法
//拷贝a到ans中
//string ans=a;
for(int i=0;i<b.length();i++){
if(a[i]>=b[i]){
a[i]=a[i]-b[i]+'0';
}else
{
//就要借
int k=1;
while(a[i+k]=='0'){
a[i+k]='9';
k++;
}
//这里可以保证i+k这一位上不是0
a[i+k]= a[i+k]-'1'+'0';
a[i]=(a[i]-'0'+10-(b[i]-'0'))+'0';
}
}
reverse(a.begin(),a.end());
if(a.find_first_not_of('0')==string::npos) return "0";//从头到尾都找不到0
return a.substr(a.find_first_not_of('0'));
}
void i2s(int num,string &str)
{
stringstream ss;
ss << num;
ss >> str;
}
//转换成减法
string divide(string a,string b){
//只考虑a<b的情况
string ans="0.";
//转换成减法
for(int i=0;i<101;i++){//101次
a.append("0");
int t=0;
while(cmp(a,b)>=0){//a>=b
a=subtract(a,b);//不停地做减法
t++;//记录减法做了多少次
}
string t_str;
i2s(t,t_str);//转为str
ans.append(t_str);
}
return ans;
}
int main(){
string a="41";
string b="23";
cout<<subtract(a,b)<<endl;
for(int i=3;i<=n;i++){
string temp=b;//拷贝b
b=add(a,b);
a=temp;
//cout<<b<<""<<endl;
}
//a,b是斐波那契的n-1和n项
string ans=divide(a,b);
cout<<ans<<endl;
cout<<ans.length()-2<<endl;
return 0;
}
5、前缀判断(代码填空)
先编译通过,导入头文件,再看逻辑,验证
#include<iostream>
using namespace std;
char* prefix(char* haystack_start,char*needle_start){
char* haystack=haystack_start;//母串
char* needle=needle_start;//前缀
while(*haystack&&*needle){//两个指针都没有越界
//移动指针并判断
if(*(haystack++)!=*(needle++)) return NULL; }//if里面是填空位置
if(*needle) return NULL;
return haystack_start;
}
int main(){
cout<<prefix("abd123","abd")<<endl;
return 0;
}
6.三部排序(代码填空)
快速排序
#include<iostream>
using namespace std;
void sort3p(int *x,int len){
int mod=0;
int left=0;
int right=len-1;
while(mod<=right){
if(x[mod]<0){
int t=x[left];
x[left]=x[mod];
x[mod]=t;
left++;
mod++;
}
else if(x[mod]>0){
int t=x[right];
x[right]=x[mod];
x[mod]=t;
right--;
}else{
//==0
mod++;
}
}
}
int main(){
int arr[]={25,34,65,7,2,-1,-9};
sort3p(arr,7);
for(int i=0;i<7;i++){
cout<<arr[i]<<" ";
}
return 0;
}
7、错误票据
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<iostream>
using namespace std;
const int MaxN=10000;
int line;
int data[MaxN];
void s2i(string &str,int &num){
stringstream ss;
ss<<str;
ss>>num;
}
int main(){
scanf("%d",&line);
getchar();//去掉换行符
int index=0;
for(int i=0;i<line;++i){
string s;
getline(cin,s);
istringstream iss(s);//把s封装到iss
string tmp;
while(getline(iss,tmp,' ')){//getline自带分割功能,输入流要是iss,每次切割封装到tmp当中
s2i(tmp,data[index++]);//先取值,在加加
}
}
//最终index就是数据的个数
// cout<<index<<endl;
//排序
sort(data,data+index);
int a,b;
for(int i=1;i<index;i++){
if(data[i]==data[i-1]+2) a=data[i-1];
if(data[i]==data[i-1]) b=data[i];
}
printf("%d %d",a,b);
return 0;
}
8、翻硬币
#include<iostream>
using namespace std;
int main(){
string src;
string target;
getline(cin,src);
getline(cin,target);
int n=src.length();
int start=-1;
int ans=0;
for(int i=0;i<n;++i){
src[i]!=target[i];
if(start==-1)//还没标记带一个标记
{
start=i;
}
else//第一个位置已经标记,现在已经找到第二个位置
{
ans+=(i-start);
start=-1;
}
}
cout<<ans<<endl;
return 0;
}
9、带分数
暴力枚举(使用substr会超时)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
int n,ans=0;
scanf("%d",&n);
string s="123456789";
do{
for(int i=1;i<=7;i++){//加号前的串长度
string a=s.substr(0,i);
//字符串转为整数
int inta=atoi(a.c_str());
if(inta>=n)break;
//插入除号
for(int j=1;j<9-i-1;j++) {//加号、除号两个串之间的长度
string b=s.substr(i,j);
string c=s.substr(i+j);//这是除号后面的串
int intb=atoi(b.c_str());
int intc=atoi(c.c_str());
if(intb%intc==0&&inta+intb/intc==n) ans++;
}
}
}while(next_permutation(s.begin(),s.end()));
printf("%d",ans);
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int parse(const char *arr,int pos,int len){
int ans=0;
int t=1;
for(int i=pos+len-1;i>=pos;i--){
ans+=(arr[i]-'0')*t;
t*=10;
}
return ans;
}
int main(){
int n,ans=0;
scanf("%d",&n);
string s="123456789";
do{
const char *str=s.c_str();//返回const*
for(int i=1;i<=7;i++){//加号前的串长度
//string a=s.substr(0,i);
//字符串转为整数
int inta=parse(str,0,i); //atoi是一个函数
if(inta>=n)break;
//插入除号
for(int j=1;j<9-i-1;j++) {//加号、除号两个串之间的长度
string b=s.substr(i,j);
string c=s.substr(i+j);//这是除号后面的串
int intb=parse(str,i,j);
int intc=parse(str,i+j,9-i-j);
if(intb%intc==0&&inta+intb/intc==n) ans++;
}
}
}while(next_permutation(s.begin(),s.end()));
printf("%d",ans);
return 0;
}
输入2013结果出错
10、连号区间数
#include<iostream>
#include<cstdio>
using namespace std;
int n;//声明为全=全局变量可以自动初始化
int arr[50000];
int ans;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
for(int j=0;j<=n-1;j++){
int max=arr[j+1];
int min=arr[j];
for(int i=j;i<=n-1;i++){
if(arr[i]>max)max=arr[i];
if(arr[i]<min)min=arr[i];
if(i==j) ans++;
else{
if(max-min+1==i-j+1) ans++;//j-i形成连号区间
}
}
}
printf("%d\n",ans);
return 0;
}