牛客IOI周賽17-普及組

本博客只包含比賽 後三題 題解(最後一題僅含代碼)

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;
    }
}

略,題目沒看懂

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章