2017 Multi-University Training Contest - Team 8
rank:217/883
我们(kugwzk)好菜啊....怎么又被学弟们打爆了啊。。。学弟们都嚷嚷着要去区域赛了啊。。。
1001
线段树合并,预先处理出每个值在最终的序列中的位置,维护一个前缀和的和的标记,然后在dfs的过程中线段树合并。时间复杂度为O(nlogn),空间复杂度就大了一点,补题的时候卡了半天的内存。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#define maxn 100002
#define inf 0x3f3f3f3f
#define REP(i,x,y) for(int i=x;i<(y);i++)
#define RREP(i,x,y) for(int i=x;i>(y);i--)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int n,a[maxn],root[maxn],tot;
pii aa[maxn];
vector<int>e[maxn];
int ls[maxn*18],rs[maxn*18],Size[maxn*18];
ll sum1[maxn*18],sum2[maxn*18];
void build(int& rt,int pos,int l,int r) {
if(!rt) rt=++tot;
Size[rt]=1;
sum1[rt]=sum2[rt]=aa[pos].first;
if(l==r) return ;
int m=((l+r)>>1);
if(pos<=m) build(ls[rt],pos,l,m);
else build(rs[rt],pos,m+1,r);
}
int Merge(int x,int y) {
if(!x||!y) return x+y;
ls[x]=Merge(ls[x],ls[y]);
rs[x]=Merge(rs[x],rs[y]);
Size[x]=Size[ls[x]]+Size[rs[x]];
sum1[x]=sum1[ls[x]]+sum1[rs[x]];
sum2[x]=sum2[ls[x]]+1LL*Size[rs[x]]*sum1[ls[x]]+sum2[rs[x]];
return x;
}
void dfs(int rt,int fa) {
build(root[rt],a[rt],1,n);
REP(i,0,e[rt].size()) {
if(e[rt][i]==fa) continue;
dfs(e[rt][i],rt);
Merge(root[rt],root[e[rt][i]]);
}
}
int main()
{
int T;scanf("%d",&T);
while(T--) {
scanf("%d",&n);
tot=0;
REP(i,1,n+1) {
root[i]=0;
e[i].clear();
}
REP(i,1,n+1) {
scanf("%d",&a[i]);
aa[i]=make_pair(a[i],i);
}
sort(aa+1,aa+1+n);
REP(i,1,n+1) a[i]=lower_bound(aa+1,aa+1+n,make_pair(a[i],i))-aa;
REP(i,1,n) {
int u,v;scanf("%d %d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
for(int i=1;i<=n;i++) {
printf("%I64d ",sum2[root[i]]);
}
puts("");
for(int i=1;i<=tot;i++) Size[i]=ls[i]=rs[i]=sum1[i]=sum2[i]=0;
}
}
1002
李大爷比赛的时候貌似写错了一些地方,赛后补过了。
#include <bits/stdc++.h>
const int mod = 1e9+7;
const double ex = 1e-10;
#define inf 0x3f3f3f3f
using namespace std;
int sum[3000006];
int val[3000006];
int not_prime[2000050],prime[2000050],mu[2000050],tot;
void getmu(int n){
not_prime[0]=not_prime[1]=1;
mu[1]=1;
for (int i = 2; i<=n; i++){
if(!not_prime[i]){
mu[i]=-1;
prime[++tot]=i;
}
for(int j=1;j<=tot&&prime[j]*i<=n;j++){
not_prime[prime[j]*i]=1;
if(i%prime[j]==0){
mu[prime[j]*i]=0;
break;
}
mu[prime[j]*i]=-mu[i];
}
}
}
void init()
{
for (int i = 1;i<=1000000;i++)
{
sum[i] = (sum[i] + 1) % mod;
sum[i+1] = (sum[i+1] - 1+mod) % mod;
int cnt = 2;
for (int j = i+1; j<=1000000 ;j+=i)
{
sum[j]=(sum[j] + cnt) % mod;
sum[j+i]=(sum[j+i] - cnt + mod) % mod;
cnt++;
}
}
for (int i = 1;i<=1000000 ;i++)
sum[i] = val[i] = (sum[i] + sum[i-1]) % mod;
for (int i = 2; i<=1000000;i++)
{
if (mu[i]==0) continue;
for (int j = i; j<=1000000 ;j+=i)
sum[j] = ( sum[j] + mu[i]*val[j/i] + mod ) % mod;
}
for (int i = 1;i<=1000000 ;i++)
sum[i] = (sum[i] + sum[i-1]) % mod;
}
int main()
{
int N;
getmu(1000000);
init();
while (scanf("%d",&N) == 1)
{
printf("%d\n",(sum[N])%mod);
}
return 0;
}
1008
直接暴力bitset加剪枝。正解则是通过限制2推出了一些性质。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
int n,K;
bitset<2000010> bit;
int T,a[maxn],mmax,mmin;
char op[maxn][2];
int main()
{
scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&K);
mmax=0,mmin=0;
for (int i=0;i<n;++i)
scanf("%d",&a[i]);
for (int i=0;i<n;++i)
scanf("%s",op[i]);
mmax=mmin=0;
for (int i=0;i<n;++i) {
if (op[i][0]=='L') {
mmax+=a[i];
}
if (op[i][0]=='D') {
mmin-=a[i];
}
if (op[i][0]=='N') {
mmax+=a[i];
mmin-=a[i];
}
}
if (K>mmax||K<mmin) {
puts("no");
continue;
}
bit.reset();
bit[1000005]=1;
int flag=0;
for (int i=0;i<n;++i) {
if (op[i][0]=='N') {
bit=bit|(bit>>a[i]);
bit=bit|(bit<<a[i]);
} else if (op[i][0]=='L')
bit=bit|(bit<<a[i]);
else if (op[i][0]=='D')
bit=bit|(bit>>a[i]);
if (bit[1000005+K]==1) {
flag=1;
break;
}
}
if (flag)
puts("yes");
else
puts("no");
}
return 0;
}
1009
容斥一下。
#include <bits/stdc++.h>
using namespace std;
const int maxn=2005;
const long long mod=1e9+7;
long long C[maxn][maxn],Pow[maxn];
int T;
long long n,m;
inline long long ksm(long long x,long long n) {
long long ret=1;
while (n>0) {
if (n&1)
ret=ret*x%mod;
n>>=1;
x=x*x%mod;
}
return ret;
}
inline long long solve(long long a,long long b,long long n) {
long long coe=1,now=0;
for (int i=a;i>=1;--i) {
now=(now+coe*C[a][i]*Pow[i]%mod+mod)%mod;
coe=-coe;
}
now=now*C[m][b]%mod*Pow[b]%mod;
return now;
}
int main()
{
for (int i=0;i<maxn;++i) {
C[i][0]=C[i][i]=1;
for (int j=1;j<i;++j)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
/*
for (int i=0;i<6;++i)
for (int j=0;j<=i;++j)
printf("%I64d%c",C[i][j],j==i?'\n':' ');
*/
scanf("%d",&T);
while (T--) {
scanf("%I64d%I64d",&n,&m);
for (int i=1;i<=m;++i)
Pow[i]=ksm(i,n);
long long res=0;
for (int i=1;i<=m-1;++i)
res=(res+solve(i,m-i,n))%mod;
printf("%I64d\n",res);
}
return 0;
}

浙公网安备 33010602011771号