您的位置:首页 > 其它

2014年蓝桥杯整理

2020-04-05 18:24 92 查看

神奇的算式

由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;
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
小熊迪帝 发布了12 篇原创文章 · 获赞 0 · 访问量 175 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: