概述
今天读错了好多题 贡献为负 对不起队友。。
Killer Names
注意MOD不要少些几个 中间变量会爆long long
dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1]*j;
这个转移
前i-1 有j个字母了 那我当前位置随便填写前j中的一个
+
前i-1有j-1个字母了 那我当前位置写一个新的+之前j-1挑一个替换成新的然后当前位置写那个旧的
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MOD=1e9+7;
ll fact[2048][2048];
ll C(ll n,ll m){
if(m==0||n==m) return 1;
if(fact[n][m]) return fact[n][m];
return fact[n][m]=(C(n-1,m)+C(n-1,m-1))%MOD;
}
ll dp[2024][2024];
ll solve(ll n,ll m){
memset(dp,0,sizeof(dp));
//dp[i][j] 表示到第i个用了j个字母的方案数
for(int i=1;i<=n;i++) dp[i][1]=1;
for(ll i=1;i<=n;i++){
for(ll j=2;j<=min(i,m);j++){
dp[i][j]=dp[i-1][j]*j%MOD+dp[i-1][j-1]*j%MOD;
dp[i][j]%=MOD;
}
}
ll ans=0;
for(ll i=1;i<=min(n,m);i++){
for(ll j=1;i+j<=m&&j<=n;++j){
(ans+=dp[n][i]*dp[n][j]%MOD*(C(m,i)*C(m-i,j)%MOD)%MOD)%=MOD;
}
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
ll n,m;
scanf("%lld%lld",&n,&m);
printf("%lldn",solve(n,m));
}
return 0;
}
这道题读错好几次。。漏看了条件导致题目变难系列。。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MOD=1e9+7;
ll a[10000];
char c[10000];
int main(){
int T;
scanf("%d",&T);
while(T--){
ll n,m;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i) scanf("%lld",a+i);
for(int i=1;i<=n;++i) cin>>c[i];
ll up,low;
up=low=0;
for(int i=1;i<=n;++i){
if(c[i]=='L') up+=a[i];
else if(c[i]=='D') low-=a[i];
else up+=a[i],low-=a[i];
}
if(m>=low&&m<=up) puts("yes");
else puts("no");
}
return 0;
}
树上启发式合并+树状数组
PE? 要多打一个空格才能过。。 题目的锅吧
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MOD=1e9+7;
#define MAXN 102000
#define pb push_back
#define lowbit(i) (i&(-i))
vector<int>G[MAXN];
int n,tot;
ll val[MAXN],a[MAXN],sum[MAXN],lson[MAXN],rson[MAXN],num[MAXN],ans[MAXN],pos[MAXN],siz[MAXN];
//num[MAXN] 出现了哪些权值的点
//sum[MAXN] 出现点的权值
ll SUM;
void init(){
SUM=0;
for(int i=1;i<=n;++i) G[i].clear();
for(int i=1;i<=n;++i) sum[i]=num[i]=0;
for(int i=1;i<=n;++i) lson[i]=rson[i]=siz[i]=0;
}
ll getsum(ll *arr,ll x){
ll ret=0;
for(ll i=x;i;i-=lowbit(i)){
ret+=arr[i];
}
return ret;
}
void update(ll *arr,ll x,ll val){
for(ll i=x;i<=tot;i+=lowbit(i)){
arr[i]+=val;
}
}
void dfs(int u,int fa){
siz[u]=1;
for(int i=0;i<G[u].size();++i){
int to=G[u][i];
if(to==fa) continue;
if(!lson[u]) lson[u]=to;
else rson[u]=to;
dfs(to,u);
siz[u]+=siz[to];
}
if(lson[u]&&rson[u]&&siz[lson[u]]>siz[rson[u]]) swap(lson[u],rson[u]);
}
void add(int id){
SUM+=(getsum(num,tot)-getsum(num,id)+1)*val[id];//额外加上(比他大的个数+1)*自己
SUM+=getsum(sum,id);//比他小的再加一次
update(num,id,1);//id 出现 记录一下
update(sum,id,val[id]);//权值出现
}
void del(int id){
update(num,id,-1);//id消失
update(sum,id,-val[id]);//权值消失
SUM-=(getsum(num,tot)-getsum(num,id)+1)*val[id];//减掉他产生的贡献值
SUM-=getsum(sum,id);//减掉之前数的偏移量
}
void clr(int u){
del(pos[u]);
if(lson[u]) clr(lson[u]);
if(rson[u]) clr(rson[u]);
}
void merge(int u){
add(pos[u]);
if(lson[u]) merge(lson[u]);
if(rson[u]) merge(rson[u]);
}
void solve(int u){
if(!lson[u]){
ans[u]=a[u];
add(pos[u]);
return;
}
solve(lson[u]);
if(rson[u]){
clr(lson[u]);
solve(rson[u]);
merge(lson[u]);
}
add(pos[u]);
ans[u]=SUM;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=1;i<=n;++i) scanf("%lld",a+i),val[i]=a[i];
sort(val+1,val+1+n);
tot = unique(val+1,val+1+n)-val-1;//去重
for(int i=1;i<=n;++i) pos[i]=lower_bound(val+1,val+tot+1,a[i])-val;//离散化
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
G[u].pb(v);
G[v].pb(u);
}
dfs(1,0);//标记 父亲节点 左儿子的siz较小
solve(1);//处理答案
for(int i=1;i<=n;++i) printf("%lld ",ans[i]);
printf("n");
}
return 0;
}
最后
以上就是谨慎铃铛为你收集整理的2017 hdu多校 第八场的全部内容,希望文章能够帮你解决2017 hdu多校 第八场所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复