2014年蓝桥杯整理

神奇的算式

由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。
比如:
6 x 210 = 1260
8 x 473 = 3784
27 x 81 = 2187
1.枚举,排序,比较

#include<iostream>
#include<sstream>
#include<algorithm>
using namespace std;
int ans;
void i2s(long long x,string &basic){//字符串转成数字 
 stringstream ss;
 ss<<x;
 ss>>basic;
}
bool check(long long src,long long r){
 string src_str,r_str;
 i2s(r,r_str);
 i2s(src,src_str);
 sort(r_str.begin(),r_str.end());
 sort(src_str.begin(),src_str.end());//排序比较 
 if(r_str==src_str) return true;
 return false;
}
int main(){
 for(int i=1;i<10;i++){
  for(int j=0;j<10;j++){ 
  if(i!=j)
  for(int k=0;k<10;k++)
  if(k!=j&&k!=i)
  for(int l=0;l<10;l++)
  if(l!=j&&l!=i&&l!=k)
  {
   long long src=i*1000+j*100+k*10+l;//ijkl四位数 
   //
   if(i!=0){
   long long r1=i*(j*100+k*10+l);
       if(check(src,r1))
       cout<<i<<"*"<<j<<k<<l<<"="<<r1<<endl;
    } 
   if(k!=0) {
   long long r2=(i*10+j)*(k*10+l);
   if((i*10+j)<(k*10+l)&&check(src,r2))
   cout<<i<<j<<"*"<<k<<l<<"="<<r2<<endl;
   }
   /*if(l!=0){
   long long r3=(i*100+j*10+k)*l;
   if(check(src,r3)) 
   cout<<i<<j<<k<<"*"<<l<<"="<<r3<<endl;
   }*/ 
  }
  } 
 }
 return 0;
}

扑克序列

A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。
要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。
1.全排列+检查

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
bool check(const string &b);
int main(){
 string s="223344AA";
 do{
  if(check(s)) cout<<s<<endl;
 }while(next_permutation(s.begin(),s.end()));
 return 0; 
}
bool check(const string &b){
 if(b.rfind('A')-b.find('A')==2&&
 b.rfind('2')-b.find('2')==3&&
 b.rfind('3')-b.find('3')==4&&
 b.rfind('4')-b.find('4')==5) return true;
 return false;
}

蚂蚁感冒

长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。 接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。
1.这不是模拟
2.突破思维禁锢

#include<iostream>
using namespace std;
int arr[51];
int main(){
 int n;
 cin>>n;
 for(int i=0;i<n;i++){
  cin>>arr[i];
 }
 int x=arr[0];
 if(x>0){
  int ans=1;
  for(int i=0;i<n;i++){
   if(arr[i]<0&&-arr[i]>x)
   ans++;
  }
  if(ans!=1)//有从右到左的
  {
   for(int i=0;i<n;i++){
   if(arr[i]>0&&arr[i]<x) //紧随其后的 
   ans++;
   } 
 }
  cout<<ans<<endl;
}
    if(x<0){
     int ans=1;
     for(int i=0;i<n;i++){
   if(arr[i]>0&&arr[i]<-x)
   ans++;
  }
  if(ans!=1){
   for(int i=0;i<n;i++){
   if(arr[i]<0&&-arr[i]>-x)
   ans++;
  }
 }
 cout<<ans<<endl;
}
return 0;
}

斐波那契

1.快速斐波那契
2.快速乘法

#include<iostream>//快速斐波那契 
#include<cstring>
//f(x)=f(x+1)-f(x-1) 所以和等价于f(n+2)-1 
using namespace std;
typedef  long long ll;
ll n,m,mod;
/*void  solve1(){
 ll a=1,b=1;
 if(m>=n+2){
  for(int i=3;i<=n+2;i++){
   ll t=a;
   a=b;
   b+=t; 
  }
  cout<<b%mod-1;
 } else {
  ll fibm,fibn_2=0;
  for(int i=3;i<=n+2;i++){
   ll t=a;
   a=b;
   b+=t; 
   if(i==m) fibm=b;
  }
  fibn_2=b;
  cout<<fibn_2%fibm%mod-1;
 }
}*/
class M{
 public:
  ll data[2][2];
  M(){memset(data,0,sizeof(data));}
};
//快速乘法
ll mm(ll a,ll b,ll mod){
 if(a>b){
  ll t=a;
  a=b;
  b=t; 
 }
 ll x=0;
 while (b!=0){
  if((b&1)==1) x=(x+a)%mod;
 a=a*2;
 a%=mod; 
 b>>=1;
    }
    return x;
} 
ll mm(ll a,ll b){
 if(a>b){
  ll t=a;
  a=b;
  b=t; 
 }
 ll x=0;
 while (b!=0){
  if((b&1)==1) x=(x+a);
 a=a*2; 
 b>>=1;
    }
    return x;
} 
//将两个2*2的矩阵相乘 
M *mul(M *m1,M *m2,ll mod){
 M *ans=new M();
 ans->data[0][0]=(mm(m1->data[0][0],m2->data[0][0],mod)+mm(m1->data[0][1],m2->data[1][0],mod))%mod;
 ans->data[0][1]=(mm(m1->data[0][0],m2->data[0][1],mod)+mm(m1->data[0][1],m2->data[1][1],mod))%mod;
 ans->data[1][0]=(mm(m1->data[1][0],m2->data[0][0],mod)+mm(m1->data[1][1],m2->data[1][0],mod))%mod;
 ans->data[1][1]=(mm(m1->data[1][0],m2->data[0][1],mod)+mm(m1->data[1][1],m2->data[1][1],mod))%mod;
    return ans;
}
M *mul(M *m1,M *m2){
 M *ans=new M();
 ans->data[0][0]=(mm(m1->data[0][0],m2->data[0][0])+mm(m1->data[0][1],m2->data[1][0]));
 ans->data[0][1]=(mm(m1->data[0][0],m2->data[0][1])+mm(m1->data[0][1],m2->data[1][1]));
 ans->data[1][0]=(mm(m1->data[1][0],m2->data[0][0])+mm(m1->data[1][1],m2->data[1][0]));
 ans->data[1][1]=(mm(m1->data[1][0],m2->data[0][1])+mm(m1->data[1][1],m2->data[1][1]));
    return ans;
}
//m的n次幂
M *mpow(M *m,int n,ll mod){
 M *E =new M();//单位矩阵
 E->data[0][0]=1;
 E->data[1][1]=1;
 while(n!=0){
  if(n&1==1) {
   E=mul(E,m,mod);
  }
  m=mul(m,m,mod);//按平方倍增
  n>>=1; 
 } 
 return E;
} 
M *mpow(M *m,int n){
 M *E =new M();//单位矩阵
 E->data[0][0]=1;
 E->data[1][1]=1;
 while(n!=0){
  if(n&1==1) {
   E=mul(E,m);
  }
  m=mul(m,m);//按平方倍增
  n>>=1; 
 } 
 return E;
} 
ll fib(ll i,ll mod){
 M *A=new M();
 A->data[0][0]=1;
 A->data[0][1]=1;
 M *B =new M();
 B->data[0][0]=1;
 B->data[0][1]=1;
 B->data[1][0]=1;
 M *ans=mul(A,mpow(B,i-2,mod),mod);
 return ans->data[0][0];
}
ll fib(ll i){
 M *A=new M();
 A->data[0][0]=1;
 A->data[0][1]=1;
 M *B =new M();
 B->data[0][0]=1;
 B->data[0][1]=1;
 B->data[1][0]=1;
 M *ans=mul(A,mpow(B,i-2));
 return ans->data[0][0];
}
void solve2(){
 if(m>=n+2){
  cout<<fib(n+2,mod)-1;
 }
 else {
 //cout<<(fib(m-1)*(fib(n+2-m)%fib(m)))%fib(m)%mod-1<<" ";
 //cout<<fib(m)<<endl;
 cout<<fib(n+2,fib(m))%mod-1;
 }
}
int main(){
    cin>>n>>m>>mod;
// solve1();
  //for(int i=3;i<10;i++)
  //cout<<fib(i,mod)<<endl; 
  solve2();
 return 0;
 } 

波动数列

1 3 0 2 -1 1 -2 …
这个数列中后一项总是比前一项增加2或者减少3。
栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?
输入的第一行包含四个整数 n s a b,含义如前面说述
 输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数

/*
dp(i,j)表示从集合U(假设集合中元素从小到大排列)
中前 i 个数中选择,使得和为 j 总共有几种选择
当 i > j 时, 此时第 i 个元素不可以选
(因为选了的话元素之和肯定大于 j) dp( i, j ) = dp( i-1, j )
 当 i <= j 时, 第 i 个元素要么选, 要么不选
dp( i, j ) = dp( i-1, j) + dp( i-1, j- i )
*/ 
#include<iostream>// nx+(n(n-1)/2)a==s
#include<vector>
#include<cstring>
using namespace std;
int n,s,a,b;
long long ans=0;
const int MOD=100000007;
void dp2(){
 int t=n*(n-1)/2;
 int dp[2][t+1];//滚动数组 
 memset(dp,0,sizeof(dp));
 dp[0][0]=1;
 dp[1][0]=1;
 /*for(int i=0;i<n;i++){
 dp[i][0]=1;
 }*/
 int row=0;
 for(int i=1;i<n;i++){
  row=1-row;
  for(int j=1;j<=i*(i+1)/2;j++){
  if(i>j) dp[row][j]=dp[1-row][j];
  else dp[row][j]=dp[1-row][j]+dp[1-row][j-i];
 }
 }
 for(int  ta=0;ta<=t;ta++)
 {
 if((s-ta*a+(t-ta)*b)%n==0);//a的个数与b的个数 
 ans+=dp[row][ta];
 }
 cout<<ans<<endl; 
} 
/*void dfs(int x,int cnt,int sum,vector<int> path){
 if(cnt==n){
  
  if(sum==s) {
  ans++;
  for(int i=0;i<path.size();i++)
  cout<<path[i]<<" ";
  cout<<endl;
  }
  if(ans>MOD) ans%=MOD;
  return;
 }
 path.push_back(x+a);
 dfs(x+a,cnt+1,sum+x+a,path);
 path.erase(path.end()-1);
 path.push_back(x-b);
 dfs(x-b,cnt+1,sum+x-b,path);
}*/
/*void solve2(){
    int t=n*(n-1)/2;
 int x;
 int x1=(s-a*n*(n-1)/2)/n;
 int x2=(s+b*n*(n-1)/2)/n;
 //枚举首项 
 for(x=x1;x<=x2;x++){
     //对x进行初步检测
  for(int tA=0;tA<=t;tA++) 
 {    long long cal=x*n+tA*a-(t-tA)*b;
 if(cal==s){ vector<int> path;//观察中间项 
  path.push_back(x); 
  dfs(x,1,x,path);
 }
}
}
}*/
int main(){
 cin>>n>>s>>a>>b;//n个数,s总和 
     //solve2();
     dp2();
 //cout<<ans<<endl;
 return 0;
}
//动态规划经典题 

一维数组解法

#include<iostream>
using namespace std;
#define Mod 100000007
typedef long long ll;
ll n,s,a,b;
ll ans;
int dp[1000*1000];//一维数组 
void dp3(){
 int t=n*(n-1)/2;
 dp[0]=1;
 for(int i=1;i<n;i++)
 for(int j=i*(i+1)/2;j>=i;j--)
 dp[j]=(dp[j]+dp[j-i])%Mod;
 for(ll ta=0;ta<=t;ta++){
  if((s-ta*a+(t-ta)*b)%n==0)
  (ans+=dp[ta])%=Mod;
 }
 cout<<ans<<endl;
}
int main(){
 cin>>n>>s>>a>>b;
 dp3();
 return 0;
}
 

地宫取宝

X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。小明被带到地宫的入口,国王要求他只能向右或向下行走。走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
  输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
  1.记忆型搜索
2.剪枝

#include<iostream> 
#include<cstring>
using namespace std;
const int mod=1000000007;
int n,m,k;
int data[50][50];
int cache[50][50][14][13];//记忆型搜索 
//long long ans;
/*void dfs(int x,int y,int max,int cnt){
 if(x==n||y==m) return;
 int cur=data[x][y];
 if(x==n-1&&y==m-1){
  if(cnt==k||(cnt==k-1&&cur>max)){
   ans++;
   if(ans>mod) ans%=mod;
  }
 }
 if(cur>max){//取物品 
  dfs(x,y+1,cur,cnt+1);
  dfs(x+1,y,cur,cnt+1);
 }
 dfs(x,y+1,max,cnt);
 dfs(x+1,y,max,cnt); 
} */
long long dfs2(int x,int y,int max,int cnt){//cnt是手上宝物数目
 //查缓存
 if(cache[x][y][max+1][cnt]!=-1) return cache[x][y][max+1][cnt]; 
 if(x==n||y==m||cnt>k) return 0;
 long long ans=0;
 int cur=data[x][y];//当前宝贝价值 
 if(x==n-1&&y==m-1){//出口 
  if(cnt==k||(cnt==k-1&&cur>max)){
   ans++;
   if(ans>mod) ans%=mod;
  }
  return ans;
 }
 if(cur>max){//取物品 
  ans+=dfs2(x,y+1,cur,cnt+1);
  ans+=dfs2(x+1,y,cur,cnt+1);
 }
 ans+=dfs2(x,y+1,max,cnt);
 ans+=dfs2(x+1,y,max,cnt);
 cache[x][y][max+1][cnt]=ans%mod;//记录
 return ans%mod; 
} 
int main(){
 cin>>n>>m>>k;
 memset(cache,-1,sizeof(cache));
 for(int i=0;i<n;i++){
  for(int j=0;j<m;j++){
   cin>>data[i][j];
  }
 }
 cout<<dfs2(0,0,-1,0);
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2022年蓝桥杯Java A组是中国著名的计算机竞赛之一,该比赛旨在发掘和培养优秀的Java程序设计人才。参赛者需要具备一定的Java编程基础和算法思维能力,通过解决一系列实际问题来展示自己的技术水平。 蓝桥杯Java A组比赛内容将涉及Java语言基础知识、面向对象编程、数据结构与算法、数据库等方面。参赛选手需要通过模拟真实的工作场景,设计和实现各种功能模块,展现出自己解决问题的能力和代码的优雅性。 蓝桥杯Java A组比赛对于参赛者来说是一次难得的锻炼机会。通过参加比赛,可以学习到实际项目中常用的技术和解决问题的思路,提高自己的编程能力。同时,这也是一个展示自己才华和与其他选手竞争的舞台,可以通过与其他优秀选手的交流互动,拓宽自己的视野,并且与同龄人一起追求计算机编程的进步。 参加蓝桥杯Java A组比赛,不仅可以提升自己的技术能力,还能为自己的未来发展增加一份宝贵的竞赛经验。很多优秀的程序员和企业都非常看重蓝桥杯的参赛者,因为这代表着他们在编程领域具备一定的实力和潜力。 总而言之,参加2022年蓝桥杯Java A组是一个对自己实力的检验和提高的机会,同时也是一个与其他优秀选手竞争的平台,可以通过比赛锻炼自己的技术能力和解决问题的能力。参赛者在比赛中要保持冷静和耐心,学会与其他选手交流和合作,相信通过努力,一定能够在比赛中取得好的成绩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值