比赛链接
@[toc]
求导
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld
题目描述
输入描述:
给出一个数 n
输出描述:
输出求 x^n^求 n - 1 次导后 x 前的系数。(答案对 10^9^+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; }