A.Health M Death
考试情况(题解)
水题,判断n能不能整除m即可
code
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
if(m%n==0) cout<<"Yes";
else cout<<"No";
return 0;
}
B.Many Oranges
考试情况(题解)
一开始写了一个没有优化的暴力
果然T了
根据题意思考优化
通过一种方式,使第一次找到的值一定为最大值即可大大减少时间复杂度
从小到大(从大到小)枚举可能成立的橘子数量,内层暴力枚举是否能恰好使用这么多橘子满足题意即可
code
#include<bits/stdc++.h>
using namespace std;
bool f1[1000000];
int main()
{
int a,b,w,maxn=-1,minn=1e9;
bool f=0;
cin>>a>>b>>w;
w*=1000;
int L=ceil(w*1.0/b),R=w/a;
for(int i=L;i<=R;i++)
{
for(int j=0;j<=i;j++)
{
for(int k=a;k<=b;k++)
{
int x=k*j;
int y=w-x;
int z=y/k;
if(z*y+k*j==w)
{
cout<<i<<' ';
f=1;
break;
}
}
if(f==1) break;
}
if(f==1) break;
}
if(f==0)
{
cout<<"UNSATISFIABLE";
return 0;
}
for(int i=R;i>=L;i--)
for(int j=0;j<=i;j++)
for(int k=a;k<=b;k++)
{
int x=k*j;
int y=w-x;
int z=y/k;
if(z*y+k*j==w)
{
cout<<i;
return 0;
}
}
return 0;
}
C.Comma
考试情况
大致是一道数论题吧(或者是什么我也不知道)
总之被我的六行 if 给卡掉了
代码通俗易懂,带两组数据试试就可以理解了
code
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
cin>>n;
if(n<1000) cout<<0;
else if(n<=999999) cout<<n-999;
else if(n<=999999999) cout<<n-999+n-999999;
else if(n<=999999999999) cout<<n-999+n-999999+n-999999999;
else if(n<=999999999999999) cout<<n-999+n-999999+n-999999999+n-999999999999;
else cout<<n-999+n-999999+n-999999999+n-999999999999+1;
return 0;
}
D.Shipping Center
考试情况
一道贪心题目,做dp做傻了,没敢去写这个贪心
另外也没注意到数据范围这么小!
所以…没写
题解
模拟题中的过程
有一个关键的点,每个箱子只能放一个物品!
可以利用贪心算法,先把物品按价值大小排序,然后把这个物品塞到能装下它的最小的箱子中
统计加起来的价值即可
#include<bits/stdc++.h>
using namespace std;
const int N=55;
int x[N],q[N],n,m,Q,l,r;
bool vis[N];
struct node
{
int w,v;
}a[N];
bool cmp(node x,node y)
{
return x.v>y.v;
}
int main()
{
scanf("%d%d%d",&n,&m,&Q);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].w,&a[i].v);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;i++) scanf("%d",&x[i]);
for(int i=1;i<=Q;i++)
{
memset(vis,0,sizeof(vis));
scanf("%d%d",&l,&r);
int tot=0;
for(int j=1;j<=m;j++)
if(j<l||j>r) q[++tot]=x[j];
sort(q+1,q+1+tot);
int ans=0;
for(int j=1;j<=n;j++)
for(int k=1;k<=tot;k++)
if(!vis[k]&&a[j].w<=q[k])
{
ans+=a[j].v;
vis[k]=1;
break;
}
printf("%d\n",ans);
}
return 0;
}
E.Lucky 7 Battle
考试情况
不会
题解
这是一道属于dp的简单题
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示前i位的值余数是否能为j
从后往前来推
初始化:
f
[
n
]
[
0
]
=
1
f[n][0]=1
f[n][0]=1
分别用
p
p
p和
q
q
q来表示题目中描述的两种方式:加空串和加一个数字的结果
如果是Takahashi进行选择,那么只要
p
p
p和
q
q
q有一个可以让结果为
7
7
7的倍数即可
但如果是让Aoki选择,只有
p
p
p和
q
q
q都可以让结果为
7
7
7,才能使当前结果成立
最后判断最开始的第
0
0
0位能否使
m
o
d
7
mod7
mod7的值恰好为
0
0
0即可
code
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
bool f[maxn][7];
int n;
string s,x;
int main()
{
cin>>n>>s>>x;
f[n][0]=1;
for(int i=n-1;i>=0;i--)
for(int j=0;j<7;j++)
{
bool p=f[i+1][10*j%7],q=f[i+1][(10*j+s[i]-'0')%7];
if(x[i]=='T') f[i][j]=p|q;
else f[i][j]=p&q;
}
if(f[0][0]) puts("Takahashi");
else puts("Aoki");
return 0;
}
F.Coprime Present
考试情况
不会
题解
通过一个重要的性质:辗转相除法!
即
g
c
d
(
a
,
b
)
=
g
c
d
(
a
−
b
,
b
)
,
(
a
>
b
)
gcd(a,b)=gcd(a-b,b),(a>b)
gcd(a,b)=gcd(a−b,b),(a>b)
所以
g
c
d
(
a
,
b
)
≤
(
B
−
A
)
≤
72
gcd(a,b)\leq (B-A)\leq 72
gcd(a,b)≤(B−A)≤72
因此a和b的最大公因数都是在
72
72
72以内的
答案集合包含
[
1
,
72
]
[1,72]
[1,72]范围的质因数每个最多出现一次
[
1
,
72
]
[1,72]
[1,72]的质数只有
20
20
20个,所以可以把这
20
20
20个数打表出来,用状压来解决此题
d
p
[
i
]
dp[i]
dp[i]表示状态i的质因数对应的集合个数
如果
i
(
r
e
s
)
i(res)
i(res)没有和
j
j
j相同的质因数,那么就进行状态转移,让
d
p
[
j
∣
r
e
s
]
+
=
d
p
[
j
]
;
dp[j|res]+=dp[j];
dp[j∣res]+=dp[j];
code
#include <bits/stdc++.h>
using namespace std;
long long a,b,dp[1<<20],p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71},ans=0;
int main()
{
cin>>a>>b;
dp[0]=1;
for(long long i=a;i<=b;i++)
{
int res=0;
for(int j=0;j<20;j++)
if(i%p[j]==0)
res|=1<<j;
for(int j=0;j<1<<20;j++)
if(!(res&j))
dp[j|res]+=dp[j];
}
for(int k=0;k<1<<20;k++) ans+=dp[k];
cout<<ans;
return 0;
}
总结
代码量都很小,前五道其实都可做,但只A了三道,有点太菜了
1.有些代码还是要敢于去实现(尽管是暴力)
2.好好读题