您的位置:首页 > 其它

【jzoj】2018/2/2 NOIP普及组——D组模拟赛

2018-02-02 18:43 344 查看

前言

今天五道题,难度做起来感觉很难,其实就是纸老虎233。

正题

题目1:公牛数学(jzoj1896)

就是高精乘

输入

第1..2行:每行包含一个十进制数

输出

第1行:输出两个数乘积

样例输入

11111111111111

1111111111

样例输出

12345679011110987654321

解题思路

高精度不讲

代码

#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int a1[51],a2[51],a[251],n1,n2,g,w;
void read()
{
string s1,s2;
cin>>s1>>s2;
n1=s1.size();n2=s2.size();
for (int i=1;i<=n1;i++)
{a1[i]=s1[n1-i]-48;}
for (int j=1;j<=n2;j++)
{a2[j]=s2[n2-j]-48;}
}
void cons()
{
for (int i=1;i<=50;i++)
{
for (int j=1;j<=50;j++)
{
a[i+j-1]+=a1[i]*a2[j]+g;
g=a[i+j-1]/10;
a[i+j-1]%=10;
}
}
}
void write()
{
w=200;
while (a[w]==0) w--;
for (int i=w;i>=1;i--)
{
printf("%d",a[i]);
}
}
int main()
{
//freopen("bullmath.in","r",stdin);
//freopen("bullmath.out","w",stdout);
read();
cons();
write();
}


题目2:愤怒的牛(jzoj1897)

有n个不同距离的牛棚,要放入c只牛,使它们之间的最小距离最大。

输入

第1行:两个用空格隔开的数字N和C。

第2~N+1行:每行一个整数,表示每个隔间的坐标。

输出

输出只有一行,即相邻两头牛最大的最近距离。

样例输入

5 3

1

2

8

4

9

样例输出

3

解题思路

用二分法查找答案,用贪心来判断

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,c,a[100001],l,r,k,sum,mins,mid;
int main()
{
//freopen("aggr.in","r",stdin);
//freopen("aggr.out","w",stdout);
scanf("%d%d",&n,&c);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+1+n);//排序
l=0;
r=a
;//范围
while (l<=r)
{
mid=(l+r)/2;//二分
sum=1;//放入1
k=1;//记录上一头牛
for (int i=2;i<=n;i++)
{
if (a[i]-a[k]>=mid)//如果距离够
{
sum+=1;//放牛
k=i;//记录
}
}
if (sum<c) r=mid-1;
else l=mid+1;//二分
}
printf("%d",l-1);
}


题目3:约数和(jzoj1401)

输入T组数据,然后输入n,求它的所有约数和。

输入

本题有多组数据,第一行一个T,表示有T组数据,下面T行,每行一个正整数N表示要处理的数。

输出

T行,每行一个正整数表示输入中对应的数的约数和。

样例输入

1

12

样例输出

28

解题思路

用开方优化求约数的枚举过程,用f数组记录重复的

代码

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int x,s,t,w,f[5000001];
int main()
{
scanf("%d",&t);
for (int ti=1;ti<=t;ti++)
{
scanf("%d",&x);
if (f[x]!=0) printf("%d\n",f[x]);//输出
else
{
s=0;
w=int(sqrt(double(x)));//优化
for (int i=1;i<=w;i++)
{
if (x%i==0) {s+=i;//累加
if (x/i!=i)s+=x/i;//去重
}
}
printf("%d\n",s);
f[x]=s;//记录
}
}
}


题目4:旅行(jzoj1402)

一条7000km的路上已经知道有若14个旅馆,分别距离原点

0, 990, 1010, 1970, 2030, 2940, 3060, 3930, 4060, 4970, 5030, 5990, 6010, 7000

还加入了n个旅馆,一辆车每天至少走a km,最多走b km,求旅行方案总数。

输入

第一行输入A,第二行输入B,第三行输入N(0<=N<=20),表示在出发之前又新增N个汽车旅馆,接下来N行,每行一个整数m,表示旅馆离起点的距离(0

输出

输出一共有多少种旅行方案。

样例输入

1

500

0

样例输出

0

解题思路

这里用dp,如果可以加入就累加方案数

#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,n,f[41],s;
int way[41]={0,0,990,1010,1970,2030,2940,3060,3930,4060,4970,5030,5990,6010,7000};
//预处理
int main()
{
scanf("%d%d%d",&a,&b,&n);
n+=14;
for (int i=15;i<=n;i++) scanf("%d",&way[i]);
sort(way+1,way+1+n);//快排
f[1]=1;
for (int i=2;i<=n;i++)
{
for (int j=1;j<i;j++)
{
if (way[i]-way[j]>=a && way[i]-way[j]<=b)
{
f[i]+=f[j];//dp
}
}
}
for (int i=1;i<=n;i++) if (way[i]+b>=7000) s+=f[i];//累加可以到达宾馆的方案
printf("%d",f
);//输出
}


题目5:逆序统计(1403)

给出n个数字,求出逆序对为k的排列数。

输入

从文件COUNT.IN输入。输入第一行有两个整数N 和K。其中(N<=100,K<=N*(N-1)/2)

输出

将1..N 的逆序对数量为K的特定排列的数量输出到文件COUNT.OUT。为了避免高精度计算,请将结果mod 10000以后再输出!

样例输入

5 3

样例输出

15

解题思路

从两个方向[i][j-1],[i-1][j],然后减去重复

代码

#include<cstdio>
using namespace std;
int n,k,f[101][4951];
int main()
{
scanf("%d%d",&n,&k);
f[0][0]=1;//初始化
for (int i=1;i<=n;i++)
for (int j=0;j<=k;j++)
if(j)//避免越界
{
if (i>j) f[i][j]=(f[i-1][j]+f[i][j-1])%10000;//动态转移
else f[i][j]=(f[i-1][j]+f[i][j-1]-f[i-1][j-i])%10000;//动态转移
}
else f[i][j]=f[i-1][j];
f
[k]=(f
[k]+10000)%10000;//避免负数
printf("%d",f
[k]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: