1.购物单
思路:代码比计算器算更快
输入:
180.90 88
10.25 65
56.14 90
104.65 90
100.30 88
297.15 50
26.75 65
130.62 50
240.28 58
270.62 80
115.87 88
247.34 95
73.21 90
101.00 50
79.54 50
278.44 70
199.26 50
12.97 90
166.30 78
125.50 58
84.98 90
113.35 68
166.57 50
42.56 90
81.90 95
131.78 80
255.89 78
109.17 90
146.69 68
139.33 65
141.16 78
154.74 80
59.42 80
85.44 68
293.70 88
261.79 65
11.30 88
268.27 58
128.29 88
251.03 80
208.39 75
128.88 75
62.06 90
225.87 75
12.89 75
34.28 75
62.16 58
129.12 50
218.37 50
289.69 80
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int main()
{
int n=50;
double a,b,ans;
while(n--)
{
cin>>a>>b;
ans+=a*(b/100.0);
}
cout<<ans;
return 0;
}
答案:5136.86 -> 5200
2.等差素数列
思路:先打个素数表,然后用素数枚举数列的前两项,得出公差之后,判断后面八项是否也是素数(这里不小心写成了判断后九项,多算了一项,一直wa,所以要细心)
小tips:题目要求最小公差,其实可以枚举公差,和上述方法实质相同,但是感觉思路上稍微清晰一些。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int prime[1000010];
int isprime[1000010];
int main()
{
int i,j,num=0;
for(i=0;i<1000000;i++)
isprime[i]=1;
for(i=2;i<1000000;i++)
{
if(isprime[i])
prime[num++]=i;
for(j=0;j<num&&i*prime[j]<=1000000;j++)
{
isprime[i*prime[j]]=0;
if(i%prime[j]==0)
break;
}
}
int k,d,book;
for(i=0;i<num;i++)
{
for(j=i+1;j<num;j++)
{
d=prime[j]-prime[i];
book=0;
for(k=2;k<=9;k++)
{
if((prime[i]+k*d<1000000)&&isprime[prime[i]+k*d]==1)
book=0;
else
{
book=1;
break;
}
}
if(book==0)
{
cout<<d<<endl;
break;
}
}
if(book==0)
break;
}
return 0;
}
答案:210
3.承压计算
思路:把每一个电子秤上的示数都计算出来,排序后,用题目中的示数和最小的数做除法,得出换算单位,再乘上最大的数,即为答案
注意:cout输出double时,会自动变成科学计数法,所以这里要用printf
输入:
7
5 8
7 8 8
9 2 7 2
8 1 4 9 1
8 1 8 8 4 1
7 9 6 1 4 5 4
5 6 5 5 6 9 5 6
5 5 4 7 9 3 5 5 1
7 5 7 9 7 4 7 3 3 1
4 6 4 5 5 8 8 3 2 4 3
1 1 3 3 1 6 6 5 5 4 4 2
9 9 9 2 1 9 1 9 2 9 5 7 9
4 3 3 7 7 9 3 6 1 3 8 8 3 7
3 6 8 1 5 3 9 5 8 3 8 1 8 3 3
8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9
8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4
2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9
7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6
9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3
5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9
6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4
2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4
7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6
1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3
2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8
7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9
7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6
5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
double a[30][30];
int main()
{
int i,j;
for(i=0;i<=28;i++)
for(j=0;j<=i;j++)
cin>>a[i][j];
for(i=0;i<=28;i++)
{
for(j=0;j<=i;j++)
{
a[i+1][j]+=a[i][j]/2.0;
a[i+1][j+1]+=a[i][j]/2.0;
}
}
sort(a[29],a[29]+30);
//for(j=0;j<30;j++)
//cout<<a[29][j]<<endl;
double m=2086458231,minn=a[29][0],maxx=a[29][29];
printf("%f\n",m/minn*maxx);
return 0;
}
答案:72665192664
4.方格分割
思路:直接模拟比较复杂,可以利用两部分完全相同这一点进行思维的转换。可以将整个图看作是7*7的待分割格子,两部分完全相同——说明分割后的两部分关于中点(3,3)中心对称,即中点处一定与两部分都相邻。
从中心点开始向四周深搜,相当于切割,同时与它呈中心对称的位置进行反向切割,直到遇到边界为止。由于整个地图是正方形,终点落在四条边时总有一种重复的,所以最后答案➗4。
注意book数组标记为1的时候,和它关于中心对称的点也要标记,这样做是为了保证分割出来的两部分完全相同
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int nextx[4]={-1,1,0,0};
int nexty[4]={0,0,-1,1};
int book[7][7];
int ans;
void dfs(int x,int y)
{
if(x==0||x==6||y==0||y==6)
{
ans++;
return;
}
int nx,ny,i;
for(i=0;i<4;i++)
{
nx=x+nextx[i];
ny=y+nexty[i];
if(nx>=0&&nx<=6&&ny>=0&&ny<=6) //必定成立,可不写
{
if(book[nx][ny]==0)
{
book[nx][ny]=1;
book[6-nx][6-ny]=1; //保证对称,必须写
dfs(nx,ny);
book[nx][ny]=0;
book[6-nx][6-ny]=0;
}
}
}
return;
}
int main()
{
book[3][3]=1;
dfs(3,3);
cout<<ans/4<<endl;
return 0;
}
答案:509
7.日期问题
思路:注意日期的简单写法,还需练习
wa点:题目说A、B、C都可以等于零,judge2中忘了判断C大于零,一直wa
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
struct node{
int x,y,z;
};
node ans[20];
int cnt;
bool cmp(node n1,node n2)
{
if(n1.x==n2.x)
{
if(n1.y==n2.y)
return n1.z<n2.z;
else
return n1.y<n2.y;
}
else
return n1.x<n2.x;
}
int judge(int year)
{
if(year%4==0&&year%100!=0||year%400==0)
return 1;
return 0;
}
int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
void judge2(int a,int b,int c)
{
if(c>0&&c<=day[b]+((b==2)?judge(a):0))
{
ans[cnt].x=a;
ans[cnt].y=b;
ans[cnt].z=c;
cnt++;
}
}
void judge1(int a,int b,int c)
{
if(a>=60&&b>=1&&b<=12)
judge2(a+1900,b,c);
if(a<60&&b>=1&&b<=12)
judge2(a+2000,b,c);
}
int main()
{
int a,b,c;
scanf("%d/%d/%d",&a,&b,&c);
judge1(a,b,c);
judge1(c,a,b);
judge1(c,b,a);
sort(ans,ans+cnt,cmp);
if(cnt!=0)
printf("%04d-%02d-%02d\n",ans[0].x,ans[0].y,ans[0].z);
for(int i=1;i<cnt;i++)
if(ans[i].x!=ans[i-1].x||ans[i].y!=ans[i-1].y||ans[i].z!=ans[i-1].z)
printf("%04d-%02d-%02d\n",ans[i].x,ans[i].y,ans[i].z);
return 0;
}
8.包子凑数
思路:当两个数不互质时,即gcd不等于1,它们不能凑出的数一定是无限的;当两个数互质时,即gcd等于1,它们凑不出的数是有限的,最大为a*b-a-b。
由上可知,这些数之间不互质时可以直接输出INF;
当互质时,就要求出具体的凑不出的数。用一个book数组进行标记,枚举最大范围内所有能凑出的数,标记为1,最后累加所有标记为0的个数,即为答案。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int main()
{
int n,i,m,j;
int a[110],book[10010];
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
if(i==0)
m=a[0];
m=__gcd(m,a[i]);
book[a[i]]=1;
}
if(m!=1)
cout<<"INF"<<endl;
else
{
book[0]=1;
for(i=0;i<n;i++)
for(j=1;j+a[i]<=10000;j++)
if(book[j]==1)
book[j+a[i]]=1;
int ans=0;
for(i=0;i<=10000;i++)
if(book[i]==0)
ans++;
cout<<ans<<endl;
}
return 0;
}
9.分巧克力
思路:二分查找。注意左端点L和右端点R的选取;注意while循环的条件,不要死循环
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int h[100010],w[100010];
int main()
{
int n,k,i;
cin>>n>>k;
int maxx=0;
for(i=0;i<n;i++)
{
cin>>h[i]>>w[i];
maxx=max(maxx,max(h[i],w[i]));
}
int l=1,r=maxx,mid,cnt,ans;
while(l<=r)
{
mid=(l+r)/2;
cnt=0;
for(i=0;i<n;i++)
cnt+=(h[i]/mid)*(w[i]/mid);
if(cnt<k)
r=mid-1;
else
{
ans=mid;
l=mid+1;
}
}
cout<<ans<<endl;
return 0;
}
10.k倍区间
题意:给定一个大小为n的数列,求区间和是k的倍数的区间个数。
思路:求前缀和,如果两个位置的前缀和模k的结果相同,说明这两个前缀和的差是一个k倍的数,即这两个位置之间的数之和一定是k的倍数。
用一个book[i]数组记录模k等于i的前缀和的个数。
每求出一个位置的前缀和,模k之后若等于m,给答案累加book[m],即相当于在本位置之前的模k等于m的位置与本位置构成的区间的个数,然后将book[m]+1。
最后答案要再加上book[0],因为本身就是k的倍数的数,自己就可以构成这个区间。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int a[100010],book[100010];
int main()
{
int i,n,k,sum=0;
long long ans=0;
cin>>n>>k;
for(i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];
sum%=k;
ans+=book[sum];
book[sum]++;
}
cout<<ans+book[0]<<endl;
return 0;
}