【题解】西南科技大学第十六届ACM程序设计竞赛暨绵阳市邀请赛 BCDEF

B

先选出n-1种颜色C(n,n-1)=n
剩下的就是n-1个不同的数放n个位置
然后从n-1种颜色种选择一个作为重复的颜色 C(n-1,1)=n-1
在从n个位置选择两个放重复颜色,C(n,2)
最后n-2个位置为(n-2)!
整理:图片说明

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 1e9+7;
const int maxn = 1e6 + 4;
const int N    = 5e3 + 5;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll qpow(ll x,ll y){ll ans=1;x%=mod;assert(y>=0);while(y){ if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}
//#define LOCAL

int _,n,m,k,a[maxn];
ll f[maxn];
int main() {
#ifdef LOCAL
    freopen("RACE input.in","r",stdin);
#endif
    f[0]=1;
    for(int i=1;i<=1e6;i++) f[i]=f[i-1]*i%mod;
    while(~scanf("%d",&n)) {
        if(n==1) printf("0\n");
        else
        printf("%lld\n",(n-1)*(n-1)%mod*n%mod*n%mod*f[n-2]%mod*qpow(2,mod-2)%mod);
    }
}

C

n<=3时无解否则
AAR{AAAAA(n-4个)}R
AR数量为2+(n-4+2)=n,长度3+n-4+1=n

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 998244353;
const int maxn = 2e6 + 4;
const int N    = 5e3 + 5;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll qpow(ll x,ll y,ll mod){ll ans=1;x%=mod;assert(y>=0);while(y){ if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}
//#define LOCAL

int n,a[maxn];
int main() {
#ifdef LOCAL
    freopen("RACE input.in","r",stdin);
#endif
   while(~scanf("%d",&n)) {
      if(n<=3) printf("-1\n");
      else {
        printf("AAR");
        for(int i=1;i<=n-4;i++) printf("A");
        printf("R\n");
      }
   }
}

D

看清题意,要求的是用尽可能多的方式走到n,m。所以我们直接二进制枚举用哪些方式走,记忆化搜索看能否 走到即可

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 1e9+7;
const int maxn = 1e6 + 4;
const int N    = 100 + 5;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll qpow(ll x,ll y){ll ans=1;x%=mod;assert(y>=0);while(y){ if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}
//#define LOCAL

int _,n,m,k;
char s[maxn];
int dp[N][N][33];
struct node{int x,y ;}a[maxn];

int dfs(int n,int m,int S,int used) {
   if(n==0&&m==0) {return S==used; }
   if(dp[n][m][used]!=-1) return dp[n][m][used];
   int ans=0;
   for(int i=0;i<k;i++) {
        if(S&(1<<i)) {
            int xx=n-a[i].x,yy=m-a[i].y;
            if(xx>=0&&yy>=0) ans|=(dfs(xx,yy,S,used|(1<<i)));
        }
   }
   return dp[n][m][used]=ans;
}
int cnt(int S) {
    int ans=0;
    while(S) ans+=S%2,S/=2;
    return ans;
}
int main() {
#ifdef LOCAL
    freopen("RACE input.in","r",stdin);
#endif
    for(scanf("%d",&_);_;_--) {///
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<k;i++) {
            scanf("%s",s+1);
            int len=strlen(s+1),x=0,y=0;
            for(int j=1;j<=len;j++) {
                if(s[j]=='U') y++;
                if(s[j]=='R') x++;
            }
            a[i]={x,y};
        }
        int limit=1<<k,ans=0;
        for(int S=0;S<limit;S++) {
            memset(dp,-1,sizeof dp);
            if(dfs(n,m,S,0)) ans=max(ans,cnt(S));
        }
        printf("%d\n",ans);
    }
}

两个数的LCM就相当于将这两个数拆成 p1^k1*p2^k2...形式后每个素因子对应的k取max
那么如果我们想要LCM最大,把所有数都选是最优的方法之一
预处理后暴力即可

E

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 1e9+9;
const int maxn = 2e6 + 4;
const int N    = 5e3 + 5;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll qpow(ll x,ll y){ll ans=1;x%=mod;assert(y>=0);while(y){ if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}
//#define LOCAL

int vis[maxn],a[maxn],cnt[maxn],mx[maxn];
VI v[maxn];
int main() {
#ifdef LOCAL
    freopen("RACE input.in","r",stdin);
#endif
    for(int i=2;i<=1e5;i++) {
        if(vis[i]) continue;
        v[i].pb(i);
        for(int j=i+i;j<=1e5;j+=i) v[j].pb(i),vis[j]=1;
    }
//    for(int i=10;i<=50;i++) {
//        printf("%d:",i);
//        for(int j:v[i]) printf("%d ",j);printf("\n");
//    }
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);int d=a[i];
        for(int j:v[a[i]]) while(d%j==0) d/=j,cnt[j]++;
        for(int j:v[a[i]]) mx[j]=max(mx[j],cnt[j]);
        for(int j:v[a[i]]) cnt[j]=0;
    }
    ll ans=1;
    for(int i=1;i<=1e5;i++) {
        ans=ans*qpow(i,mx[i])%mod;
    }
    printf("%lld\n",ans);

}

F

先考虑如果配对,可以发现,当某颗子树存在某种颜色的权值>这颗子树总权值/2时那么配对数为总权值-该颜色权值,否则为总权值/2.
又因为查询的是所有子树的配对数,所以我们可以通过dfs序将子树问题转化为区间问题
那么问题就是对于各个子树区间,求某种颜色的最大权值。主席树模拟即可

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 1e9+7;
const int maxn = 2e5 + 4;
const int N    = 5e3 + 5;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll qpow(ll x,ll y){ll ans=1;x%=mod;assert(y>=0);while(y){ if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}
//#define LOCAL

int dfn[maxn],sz[maxn],seq[maxn],col[maxn],cnt[maxn],tot,n;
VI G[maxn];
void dfs(int u,int fa) {
    dfn[u]=++tot;sz[u]=1;seq[tot]=u;
    for(int v:G[u]) if(v!=fa) dfs(v,u),sz[u]+=sz[v];
}
struct node { int l,r,sum;}T[maxn*25];
int root[maxn*25],sum[maxn];
void update(int l,int r,int &x,int y,int pos,int num) {
    T[++tot]=T[y];T[tot].sum+=num;x=tot;
    if(l==r) return ;
    int mid=l+r>>1;
    if(mid>=pos) update(l,mid,T[x].l,T[y].l,pos,num);
    else update(mid+1,r,T[x].r,T[y].r,pos,num);
}
int ask(int l,int r,int x,int y,int k) {
    if(l==r) return l;
    int mid=l+r>>1;
    if((T[T[y].l].sum-T[T[x].l].sum)*2>k) return ask(l,mid,T[x].l,T[y].l,k);
    if((T[T[y].r].sum-T[T[x].r].sum)*2>k) return ask(mid+1,r,T[x].r,T[y].r,k);
    return 0;
}
int ask1(int l,int r,int x,int y,int pos) {
    if(l==r) return T[y].sum-T[x].sum;
    int mid=l+r>>1;
    if(pos<=mid) return ask1(l,mid,T[x].l,T[y].l,pos);
    else return ask1(mid+1,r,T[x].r,T[y].r,pos);
}
int main() {
#ifdef LOCAL
    freopen("RACE input.in","r",stdin);
#endif
    scanf("%d",&n);
    for(int i=1;i<n;i++) {
        int u,v;scanf("%d%d",&u,&v);
        G[u].pb(v);G[v].pb(u);
    }
    for(int i=1;i<=n;i++) scanf("%d%d",&col[i],&cnt[i]);
    dfs(1,-1);tot=0;
    for(int i=1;i<=n;i++) {
        update(1,2e5,root[i],root[i-1],col[seq[i]],cnt[seq[i]]);
        sum[i]=sum[i-1]+cnt[seq[i]];
    }
    for(int i=1;i<=n;i++) {
        int l=dfn[i],r=dfn[i]+sz[i]-1;
        int z=ask(1,2e5,root[l-1],root[r],sum[r]-sum[l-1]);
        //cout<<z<<','<<l<<','<<r<<','<<sum[r]-sum[l-1]<<',';
        if(!z) z=(sum[r]-sum[l-1])/2;
        else z=sum[r]-sum[l-1]-ask1(1,2e5,root[l-1],root[r],z);
        printf("%d\n",z);
    }
}
全部评论

相关推荐

10-09 00:50
已编辑
长江大学 算法工程师
不期而遇的夏天:1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
牛客263158796号:我领羊一面后十天不挂也不推进 今天问hr说等前序的第一批意向发完看情况再看是否推进
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务