A Once In My Life
题目
找到一个数字K,和n,相乘,结果x必须包含(1-9),且至少含有两个d。输入n,d,输出K;
赛场上,首先看的就是这道,只是感觉题意易懂,但没思路,看到a出来的人也不多,还以为代码复杂,学长说是个签到题,才发现,动一脑子就出来了,可惜,在没思考之前,就把学长的代码看完了。
代码
#include<iostream>
#include<cmath>
#define int long long
using namespace std;
const int N=1234567890;
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n,d,ans;
cin>>n>>d;
ans=N+d;//含有1-9,且d出现两次
ans=ans*pow(10,to_string(n).size())+n;
ans-=ans%n;
//余数一定小于n,如此加n再减余数,不会影响前面的数字
//而且还得到符合要求的n*k
cout<<ans/n<<'\n';
}
}
起初在担心如果n的数量级是8,这样ans*10^8,岂不是超出数据范围,多虑了,因为我要的是k,即便ans很大,最后还是要除以n,k还是在2e10范围内
B 扫雷 1
题目
赛场上用的结构体,自定义排序,比较麻烦。看了其他人的代码,很巧妙。用一个数组b存实际买的价钱,因为要买只能按照i处及其后面的价格买,也就是把i及后边最便宜的存入b数组。再直接从后往前遍历,就直接得出来了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N],n,ans,cnt;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int mn=0x3f3f3f3f;
for(int i=n;i>=1;i--)
{
mn=min(a[i],mn);
b[i]=mn;//存放i处的币,购买价格
}
for(int i=1;i<=n;i++)
{
cnt++;
if(a[i]==b[i]&&cnt>=b[i])
{
ans+=cnt/b[i];
cnt=cnt%b[i];
}
}
cout<<ans<<endl;
}
F 优秀字符串
签到题,代码省略
H. 随机栈
题意
输入n个数字,其中不断拿出n次,算出按非升序拿出的概率,并对998244353取模。
思路
算概率,也就是需要知道,每次拿的时候有几种选择,满足条件的有有几种。这就需要记录,栈里相同的数据有几个,原本想的是开个数组,存数量,但还要想办法排序,找出最小的。后来听学长的用优先队列和map写的。
不过还是错了,因为我没搞懂取模,想当然了。
除法取模,用到了逆元,和费马小定理。逆元可以用倒数来理解,
图一是从学长博客里提到的知乎里一篇文章中截的
下面的费马小定理,从学长博客偷的
还出现一个错误,就是每次取出一个数字就好了,而我把相同的全删了,这样概率就错了
代码
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#define endl '\n'
# define int long long
using namespace std;
const int mod = 998244353;
map<int, int> m;
int pow1(int a, int b)
{
int res = 1;
for (; b; b >>= 1)
{
if (b & 1)res = res * a % mod;
a = a * a % mod;
}
return res % mod;
}
signed main() {
priority_queue<int, vector<int>, greater<int> > p;//小顶堆
int n, num, l = -1, t = 0, s = 1, x = 1;
cin >> n;
for (int i = 0; i < 2 * n; i++)
{
cin >> num;
if (t != 1)
{
if (num == -1)
{
s = s * m[p.top()] % mod;//分子,可以选择的数字
x = x * p.size() % mod;//分母,队列里数字个数
if (p.top() >= l)
{
l = p.top();
m[p.top()]--;
p.pop();
}
else
t = 1;
}
else
{
p.push(num);
m[num]++;
}
}
}
if (t == 1)
cout << "0" << endl;
else
{
int ans = s * pow1(x, mod - 2) % mod;//除法取模
cout << ans << endl;
}
}
J. 排列与合数
题意
输入一个五位数,将他某种为合数的排列方式输出,没有就输出-1。
存在偶数和数字5/0, 放结尾,一定为合数,十个数选五个,就绝对存在“偶数/0/5"。
代码
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n;
string a;
cin>>n;
while(n--)
{
cin>>a;
if((a[4]-'0')%2==0||(a[4]-'0')%5==0);
else
for(int i=0;i<5;i++)
{
if((a[i]-'0')%2==0||(a[i]-'0')%5==0)
{
swap(a[i],a[4]);
break;
}
}
cout<<a<<'\n';
}
}