比赛链接:https://ac.nowcoder.com/acm/contest/5389
A:https://ac.nowcoder.com/acm/contest/5389/A
题意:求进行n-1次求导后的 前面的系数 。
思路:第一次求导时,前面系数是n,第二次是n(n-1),那么n-1次后就是(n-0)*(n-1)(n-2)……(n-(n-2))恰好是n!。至此代码也就写出来了。
//author CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7;//这里模数要用上 const ll maxn=1e5+7; const double pi=acos(-1); using namespace std; int main() { ll n; cin>>n; ll ans=1; for(int i=1;i<=n;i++) { ans*=i; ans%=mod;//模运算 } cout<<ans<<endl; return 0; }
B:https://ac.nowcoder.com/acm/contest/5389/B
题意:给你n个数的同时给你另一个数m。给你的n个数只能是0-9。问你至少要改变几个数才能使得这n个数的和大于等于m。
思路:既然数组里面的数只有10种可能的值,不妨使用一下桶排序。再来想一下,同样的使总和大于等于m,那么肯定是让当前最小的数变成9所带来的收益最大。于是贪心的思路就来了。那就是从0开始,把所有数都变成9直到当前的和大于等于m。至此代码也就可以写出来了。细节看一下代码注释。
//author CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7; const ll maxn=1e5+7; const double pi=acos(-1); using namespace std; int main() { int tong[10]={0};//桶排序 int n,m; cin>>n>>m; int a; int tot=0;//当前的总和 int ans=0; for(int i=0;i<n;i++) { cin>>a; tot+=a; tong[a]++; } m-=tot;//现在的m就是差值 int i=0; while(true)//注意理解这个循环的目的,找tot<m<=tot+i { m-=tong[i]*(9-i);//先莽一些,把当前这个数字全变成9 ans+=tong[i];//于此同时答案就要加上这次变成9的数字的个数 if(m<=0)//如果此时的和已经大于等于m了,那就说明答案不会大于这个数。 { m+=tong[i]*(9-i);//再次莽,又当它从来没有变过9。 ans-=tong[i];//答案也要减去这个数 break;//跳出循环 } else { i++;//说明此时这些数根本不够,要把下一个数里面的部分或全部变成9. } } //这个i就是贪心下还能修改的最大的数字了 if(m%(9-i)==0)//整除的话是等于 { ans+=m/(9-i); } else//不能整除需要补个1 { ans+=m/(9-i)+1; } cout<<ans<<endl; return 0; }
C:https://ac.nowcoder.com/acm/contest/5389/C
题意:给你一个数n,问你有多少种染色方法可以使染色后的n * n的矩阵是关于主对角线对称的。
矩阵的每一行只能有一列被染色,矩阵的每一列也只能有一行被染色。(吐槽一下:解释如何涂单选题答题卡怎么这么麻烦)
思路:由于是对称的,我们来想,假设我们涂的是第一行第一列,那么就会剩下一个(n-1) * (n-1)的矩阵没染色,那么如果我涂的不是第一行第一列,那么由于对称性,第x行第一列其实也就染上色了。于是,就剩下一个(n-2) * (n-2)的矩阵没染色。这个x有n-1种取法。于是状态转移方程也就写出来了dp[i]=dp[i-1]+(i-1)*dp[i-2]。然后我们直到当n=1,2,3时的方案数是1,2,4。你要是勤快点,自己画一画,n=4时,方案数是10。至此代码也就写出来了。
//author CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7; const ll maxn=1e5+7; const double pi=acos(-1); using namespace std; ll dp[maxn]={0,1,2,4}; int main() { for(int i=4;i<=maxn;i++) { dp[i]=dp[i-1]+(i-1)*dp[i-2]; dp[i]%=mod;//记得进行模运算 } int n; cin>>n; cout<<dp[n]<<endl; return 0; }
写在最后:
不会树学,D题直接傻了。这个C的状态转移方程还挺好想,想不出来可以用Excel模拟一下n=4,会加深理解。