比赛链接

求导

链接:

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

输入描述:
给出一个数 n
输出描述:
输出求 xn求 n - 1 次导后 x 前的系数。(答案对 109+7 取余)
示例1
输入
复制

5

输出
复制

120

备注:
对于50% 的数据满足n≤15

对于%100% 的数据满足 n≤10 5

题解:

第一次求导,系数为n
第二次求导,系数为n*(n-1)
。。。
第n-1次求导,系数为n*(n-1)…*2
不就是阶乘吗?
直接暴力走起

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn = 1e5 +5;
 
int main(){
   
    ll n;
	cin>>n;
    ll base=1;
    for(int i=1;i<=n;i++)
	{
   
        base=base*i%mod;
    }
    cout<<base<<endl;
    return 0;
}

猜数

链接

题意:

n个数改动前之和是大于等于m,现在给出改动后,问最少改动几个数字?

输入

2 3
1 1

输出

1

题解:

方法一 贪心

我们从最小的数字开始改,同时记录每个数字的次数
有两种情况要记录个数:第一个是把还未修改的最小数改成最大数(9)后总值还是没m大,那这个数一定要改
另一个是改完当前数就正好满足条件,那也记入答案,结束
因为数的范围都在0到9,所以可以用桶来存每个数,这样操作时同时多个操作

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 4;
int n,m,a[maxn];
int tong[12];
int main() {
   
  cin>>n>>m; 
  int sum = 0,num,ans,tot=0;
	for(int i=1;i<=n;i++)
  {
   
	cin>>a[i];
    tong[9 - a[i]]++;
    sum += a[i];
  }
  for(int i=9;i>=0;i--)
  {
   
    if(sum >= m) break;
    
     ans = tong[i] * i;
    
    if(sum + ans < m) 
	{
   
		sum += ans;
		tot += tong[i];
	}
    else
	{
   
      num = ((double)(m - sum)/(double)i+0.9);
      
      tot += num;
      
      sum += num * i;
    }
  }
  cout << tot << endl;
  return 0;
}

方法二 暴力

貌似直接暴力就可以过
排个序,然后从小将每个数补满(补到9),如果补后大于m,输出当前数的序号,如果没补满继续

答题卡

题意:

题解:

dp做法
我们要先知道所选格子的横列不能冲突,因为每个题只能有一个答案。。。

如果我们选中第一行第一列的格子,反转后还是本身,因为行列不能再选,所以剩下就成了(n-1) * (n-1)的问题
如果选的是第一行第二列,对称位置是第二行第一列,也就是第一二行和第一二列都不能再选了,就成了(n-2) * (n-2)的问题
第三行到第n行与第二种情况一样,都变成了(n-2) * (n-2)的问题
汇总一起:
第一种情况为dp[i-1],出现一次
第二种情况为dp[i-2],出现了n-1次
dp[n]=dp[n-1]+(n-1)*dp[n-2]

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+3; 
ll dp[maxn];
int main(){
   
    dp[0] = 1;
	dp[1] = 1;
	dp[2] = 2;
	dp[3] = 4;
    ll n;
    cin>>n;
    for(int i = 4 ; i <= n ;++i)dp[i] = (dp[i-1] + (i-1)*dp[i-2])%mod;
    cout<<dp[n]<<endl;
}