目录
方程整数解 【简单】
http://oj.ecustacm.cn/problem.php?id=1250
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main(void)
{
int n;
while( scanf("%d",&n) != EOF )
{
bool flag=false;
for(int i=1;i<=sqrt(n);i++)
{
for(int j=i;j<=sqrt(n);j++)
{
for(int z=j;z<=sqrt(n);z++)
{
if(i*i+j*j+z*z==n)
{
flag=true;
printf("%d %d %d\n",i,j,z);
}
}
}
}
if(!flag)
{
printf("No Solution\n");
}
}
return 0;
}
星系炸弹 【★】
http://oj.ecustacm.cn/problem.php?id=1251
本题解析:
你需要判断是不是闰年来判断二月有几天
用一个数组来保存每个月的总天数。
#include<iostream>
#include<cstdio>
using namespace std;
bool judge(int year)//判断是不是闰年
{
if(year%400==0 || (year%4==0&&year%100!=0) )
return true;
else
return false;
}
int month_demo[13]={
0,31,28,31,30,31,30,31,31,30,31,30,31};
int main(void)
{
int year,month,day,n;
while( scanf("%d %d %d %d",&year,&month,&day,&n) != EOF )
{
while(n)
{
if(judge(year))
{
month_demo[2]=29;
}
else
{
month_demo[2]=28;
}
day++;
n--;
if(day>month_demo[month])
{
day=1;
month++;
}
if(month>12)
{
month=1;
year++;
}
}
printf("%d-%02d-%02d\n",year,month,day);
}
return 0;
}
奇妙的数字 【简单】
http://oj.ecustacm.cn/problem.php?id=1252
#include<iostream>
#include<cstdio>
using namespace std;
int main(void)
{
int n=10;
long int sum1=0;
long int sum2=0;
int i=0;
while(n<10000)
{
sum1=n*n;
sum2=n*n*n;
int a[10]={
0};
while(sum1)
{
a[sum1%10]++;
sum1=sum1/10;
}
while(sum2)
{
a[sum2%10]++;
sum2=sum2/10;
}
for(i=0;i<10;i++)
{
if(a[i]!=1)
break;
}
if(i==10)
{
printf("%d\n",n);
return 0;//写的话节省时间
}
n++;
}
return 0;
}
牌型种数 【★★】有意思
http://oj.ecustacm.cn/problem.php?id=1253
暴力算法:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int a[13];
int cnt = 0;
int ans = 0;
for(a[0] = 0; a[0]<=4; a[0]++)
{
for(a[1] = 0; a[1]<=4; a[1]++)
{
for(a[2] = 0; a[2]<=4; a[2]++)
{
for(a[3] = 0; a[3]<=4; a[3]++)
{
for(a[4] = 0; a[4]<=4; a[4]++)
{
for(a[5] = 0; a[5]<=4; a[5]++)
{
for(a[6] = 0; a[6]<=4; a[6]++)
{
for(a[7] = 0; a[7]<=4; a[7]++)
{
for(a[8] = 0; a[8]<=4; a[8]++)
{
for(a[9] = 0; a[9]<=4; a[9]++)
{
for(a[10] = 0; a[10]<=4; a[10]++)
{
for(a[11] = 0; a[11]<=4; a[11]++)
{
for(a[12] = 0; a[12]<=4; a[12]++)
{
if(a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9]+a[10]+a[11]+a[12]==13)
{
cnt++;
ans = cnt;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
cout << ans << endl;
return 0;
}
分析:
总共有13种牌,每一种牌有4张,对于每一种牌,有5种情况,得到0,1,2,3,4牌
用ans表示抽取的次数,sum表示手里的牌数。
必须ans=13,且手里的牌也等于13,组合数才能加1
对于起初,ans=0,开始进行递归
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int tot,sum;
void dfs(int ans)/*ans表示抽的次数*/
{
if(ans>13||sum>13)
return;
if(sum==13&&ans==13)
{
tot++;
return;
}
for(int i=0; i<5; i++) /*对于每一种牌,抽0 1 2 3 4这5种可能是*/
{
sum+=i;/*sum表示手里有几张牌*/
dfs(ans+1);
sum-=i;
}
}
int main()
{
tot=0;/*最终的组合数*/
sum=0;
dfs(0);
printf("%d\n",tot);
return 0;
}
利用dfs,找到一个路径长度为13的路。
同时还要注意k,用来控制走了几次,走了13次
#include <iostream>
#include <cstdio>
using namespace std;
long long ans;
// cnt 计算已经拿取的张数
// k就是控制递归时,控制一直取0(也就是不拿)的情况
void dfs(int cnt, int k) {
if (cnt == 13) ans++;
if (cnt >= 13 || k >= 13) return;
for (int i = 0; i <= 4; i++)
dfs(cnt+i, k+1);
}
int main( ) {
ans = 0;
// 初始化张数为0,拿的次数初始为0
dfs(0, 0);
cout << ans << endl;
return 0;
}
饮料换购 【简单】
http://oj.ecustacm.cn/problem.php?id=1255
#include<iostream>
#include<cstdio>
using namespace std;
int main(void)
{
int n;
int sum=0;
while(cin>>n)
{
sum=n;
while(n>=3)//可以兑换
{
sum+=n/3;//加上兑换的几瓶
n=n%3+n/3;// 没有兑换的+兑换的瓶数
}
printf("%d\n",sum);
}
return 0;
}
奖券数目 【简单】
http://oj.ecustacm.cn/problem.php?id=1258
#include<iostream>
#include<cstdio>
using namespace std;
int main(void)
{
int n=0;
int sum=0;
int i;
for(i=10000;i<=99999;i++)
{
sum=i;
bool flag=false;
while(sum)
{
if(sum%10==4)
{
flag=true;
}
sum=sum/10;
}
if(!flag)
{
n++;
}
}
printf("%d\n",n);
return 0;
}
三羊献瑞 【★】
http://oj.ecustacm.cn/problem.php?id=1259
#include<cstdio>
int main(void)
{
int a1,a2,a3,a4,a5,a6,a7,a8;
int sum1,sum2;
int i=0;
for(a1=0;a1<=9;a1++)//祥
{
for(a2=0;a2<=9;a2++)//瑞
{
for(a3=0;a3<=9;a3++)//生
{
for(a4=0;a4<=9;a4++) //辉
{
for(a5=1;a5<=9;a5++) //三
{
for(a6=0;a6<=9;a6++)//羊
{
for(a7=0;a7<=9;a7++)//献
{
sum1=a1*1000+a2*100+a3*10+a4;
sum2=a5*1000+a6*100+a7*10+a2;
sum1=sum1+sum2;
bool a[10]={
false};
int count=0;
a[a1]=true;
a[a2]=true;
a[a3]=true;
a[a4]=true;
a[a5]=true;
a[a6]=true;
a[a7]=true;
for(i=0;i<10;i++)
{
if(a[i])
count++;
}
if(count==7)
{
for(i=0;i<=9;i++)
{
if(!a[i])
{
sum2=a5*10000+a6*1000+a3*100+a2*10+i;
if(sum2==sum1)
printf("%d%d%d%d\n",a5,a6,a7,a2);
}
}
}
}
}
}
}
}
}
}
return 0;
}
加法变乘法 【★】有点意思
http://oj.ecustacm.cn/problem.php?id=1260
思路: 把这四个数剔除掉
#include<cstdio>
int main(void)
{
int i,j;
int sum1,sum2;
bool flag=false;
for(i=1;i<50;i++)
{
for(j=i+2;j<50;j++)
{
sum1=1225-(i+i+1)-(j+j+1);
sum2=2015-(i*(i+1))-(j*(j+1));
if(sum1==sum2&&i!=10)
{
printf("%d\n",i);
flag=true;
break;
}
}
if(flag)
{
break;
}
}
return 0;
}
移动距离 【★★】有点意思
http://oj.ecustacm.cn/problem.php?id=1261
解题思路:
设m的坐标为(m_x,m_y)、n的坐标为(n_x,n_y)。
分析题目不难看出,两栋楼之的最短距离是,abs(m_x-n_x)+abs(m_y-n_y)
注意:千万不要以为是 abs(m_x+m_y-n_x-n_y)
我本想打算用一个数组来保存这个矩阵的值。
然后遍历数组,找到对应的值返回下标。
用下标来计算距离。
但是这样的话内存太大了,显然是不行的。
那么我们就从数值在矩阵中的特殊性入手。
题目给的矩阵有点稍微的变化,所以我们先从一个简单的矩阵来分析。数值和其在矩阵中坐标的关系。
由上图可以得到如下的结论:
设矩阵的宽是 w.
m_x=(m-1)/w
n_x=(n-1)/w
例如 1的x坐标就是 1-1/6=0
为啥是先减1 再除以w 是因为
例如: 6的x坐标为
6/6=1 而我们知道6的x坐标是 0,这显然是不对的
正确的应为 (6-1)/6=5/6=0 这才对
由上可以看到
1对应的那一列对w(即 6)取余结果都为1
2对应的那一列对w(即 6)取余结果都为2
.......
5对应的那一列对w(即 6)取余结果都为5
6对应的那一列对w(即 6)取余结果都为0
于是可以得到
if(m%w==0)
{
m_y=w-1;
}
else
{
m_y=m%w-1;//因为数组的下标是从0开始的所以-1
}
简单的我们弄懂了,接下来回到题目。
不难看出x轴坐标的规律没变
y轴坐标有点变化,
有上图可以看到 我们以数组下标从0开始为例。
奇数行的y轴坐标的规律变了。
偶数行的y轴坐标的规律不变。
于是我们要判断这个数的行数是奇数还是偶数
来计算y轴坐标。
通过分析你会发现规律并写下如下代码:
if(m_x%2==0)//判断是奇数行还是偶数行
{
if(m%w!=0)
m_y=m%w-1;
else
m_y=w-1;
}
else
{
//以12为例
if( (m%w) !=0)
m_y=w-m%w;
else //12%6==0 ,m_y=0
m_y=0;
}
总的代码如下:
#include<cstdio>
#include<cmath>
int main(void)
{
int w,m,n;
while( scanf("%d %d %d",&w,&m,&n) != EOF )
{
int m_x,m_y;
int n_x,n_y;
m_x=(m-1) / w;
n_x=(n-1) / w;
if(m_x%2==0)
{
if(m%w!=0)
m_y=m%w-1;
else
m_y=w-1;
}
else
{
if( (m%w) !=0)
m_y=w-m%w;
else
m_y=0;
}
if(n_x%2==0)
{
if(n%w!=0)
n_y=n%w-1;
else
n_y=w-1;
}
else
{
if( (n%w) !=0)
n_y=w-n%w;
else
n_y=0;
}
printf("%d\n",abs(m_x-n_x)+abs(m_y-n_y));
}
return 0;
}
打印大X 【★】
http://oj.ecustacm.cn/problem.php?id=1263
样例输入
3 9
4 21
思路:
找到位置是 “ * " 的规律。
用一个bool型的二维数组,把是 " * ”号的标记为true。
遍历二维数组是true输出星号否则输出小数点
#include<cstdio>
#include<iostream>
using namespace std;
int main(void)
{
int m,n;
int lang,width;
while(cin>>m>>n)
{
width=n;//行数
lang=m+n-1;//列数
int i,j;
bool a[1005][1005]={
false};
int m1;
m1=m;
for(i=0;i<width;i++)
{
m1=m;
while(m1>0)//左边
{
a[i][m1-1+i]=true;
m1--;
}
m1=m;
while(m1>0)//右边
{
a[i][lang-m1-i]=true;
m1--;
}
}
for(i=0;i<width;i++)
{
for(j=0;j<lang;j++)
{
if(a[i][j])
{
printf("*");
}
else
{
printf(".");
}
}
printf("\n");
}
}
return 0;
}