本博客只包含比赛 后三题 题解(最后一题仅含代码)
B、莫的难题
题目描述
埋和莫曾经是好朋友。埋是文科学霸,而莫却只是一个 OI 蒟蒻。一天,埋碰到一道难题跑来问莫。题目是这样的:有五个数字,分别是 5、2、1、3、9.莫可以取任意数字,每个数字可以取无限次。如:取两个 5,则组合为:55;取 2 与 1,则组合为:21。现在要问你所有组合中第 C(n, m)%1e9+7 (n>=m) 个数有多大?
输入描述:
第 1 行一个数 t,表示询问的次数
接下来 t 行,每行两个数 n, m;详情见题目描述。
数据范围:
对于20%的数据,保证t=1
对于10%的数据,保证n=m
对于所有数据,保证
1<=t<=1000
1<=m<=n<=100
输出描述:
t行,每行一个数字,表示所有组合中第 C(n, m)%1e9+7 (n>=m) 个大的数?
示例1
输入
2
3 2
4 3
输出
3
5
AC代码
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=1e9+7;
ll n,m,k;
ll f[maxn],inv[maxn];
ll qpow(ll a,ll b) //快速幂
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
b>>=1;
if(b)a=a*a%mod;
}
return ans%mod;
}
void init() //预处理
{
f[0]=inv[0]=1;
for(int i=1; i<maxn; i++)
{
f[i]=f[i-1]*i%mod;
inv[i]=qpow(f[i],mod-2);
}
}
ll C(ll n,ll m)
{
return f[n]*inv[n-m]%mod*inv[m]%mod;
}
char mp[5]={'1','2','3','5','9'};
int main() {
init();
ll t;sc(t);
while (t--) {
ll n, m; sc(n), sc(m);
ll a = C(n, m);
string ans="";
while(a>0){
--a;//精髓
ans+=mp[a%5];
a/=5;
}
reverse(ans.begin(),ans.end());
cout<<ans<<endl;
}
return 0;
}
原题解:而坑点就在于:五进制,但是起点是1,而不是0
我也很好奇,为什么 a--
后就可以了,好像以前有做过类似的
C、不平衡数组
题目描述
给定一个长度为 n 的数组。要求相临的数大小不相同,假如相临数的相同,
你可以通过将 a[i]+1 来改变它的大小,但是需要付出 b[i]的代价,同时对于每
个 a[i]只能加一次。问你付出的最小代价。
输入描述:
第 1 行 1 个整数 n,表示数组长度为 n
接下来 n 行,每行 2 个正整数 a[i]与 b[i],表示 a 数组中的第 i 个数,以及将第 i 个数+1 的代价。
对于20%的数据,保证b[i] = 1
对于另外10%的数据,保证所有a[i]相等
对于另外10%的数据,保证所有的a[i]不相等
对于100%的数据,1<=n<=2e5,0<=a[i]、b[i]<=1e9
输出描述:
1 行,一个数字 ans,表示最小代价。
输入
4
1 2
2 2
2 3
4 1
输出
2
AC代码
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false)
#define ll long long
#define INF (int)1e18
inline int read() {
int x = 0, neg = 1; char op = getchar();
while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
return neg * x;
}
inline void print(int x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int maxn = 2e5 + 10;
int n,a[maxn],b[maxn];
ll dp[maxn][2]; // 0 不+1, 1 加一;
signed main() {
IO;
n = read();
for(int i = 1 ; i <= n ; ++i){
a[i] = read(),b[i] = read();
dp[i][0] = dp[i][1] = INF;
}
dp[1][0] = 0; dp[1][1] = b[1];
for(int i = 2; i <= n ; ++i) {
if (a[i] != a[i - 1]) dp[i][0] = min(dp[i][0], dp[i - 1][0]);
if (a[i] != (a[i - 1] + 1)) dp[i][0] = min(dp[i][0], dp[i - 1][1]);
if ((a[i] + 1) != a[i - 1]) dp[i][1] = min(dp[i][1], dp[i - 1][0] + b[i]);
if ((a[i] + 1) != (a[i - 1] + 1)) dp[i][1] = min(dp[i][1], dp[i - 1][1] + b[i]);
}
ll ans = min(dp[n][0],dp[n][1]);
cout << ans << '\n';
return 0;
}
四种情况的递推,记住了
D、数列统计
题目描述
求以x结尾的长度为ll的不下降正整数数列一共有多少个。对911451407911451407取模
输入描述:
本题有多组数据。本题有多组数据。
第一行一个正整数T,表示数据组数。
对于每组数据:两个用空格隔开的整数l,x
输出描述:
T行,每行一个答案。
示例1
输入
2
2 1
2 3
输出
1
3
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod = 911451407;
const int maxn = 100005;
ll fac[2000005];
ll qpow(ll x,ll y){
x %= mod;
ll ans = 1;
while(y){
if(y&1) ans = ans*x%mod;
x = x*x%mod;
y >>= 1;
}
return ans;
}
int main(void){
ios::sync_with_stdio(false);
fac[0] = 1;
for(int i = 1 ; i < 2000005 ; ++i) fac[i] = fac[i-1]*i%mod;
int t;
cin>>t;
while(t--){
ll l,x;
cin>>l>>x;
ll ans = fac[x+l-2]*qpow(fac[x-1],911451405)%mod;
ans = ans*qpow(fac[l-1],911451405)%mod;
cout<<ans<<endl;
}
}
略,题目没看懂