2023icpc省賽3/13

代碼未經測試僅供參考

C題

正常寫的話就組合數搞一搞

但是不取模,那麼問題就有趣起來了

衆所周知,Σc(奇數,sum)=Σ(偶數,sum),是很對稱的,所以我剛開始猜了每個點的貢獻只有1或-1,試了幾個菊花圖後發現貢獻和兒子數量有關:a[x]*(1-x的兒子數量)

找找規律:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read()
{
    ll x;scanf("%lld",&x);return x;
}
int fa[100],d[100],sum[100];
int n;
vector<int>e[100],a;
int lca(int x,int y)
{
    while(d[x]>d[y])
        x=fa[x];
    while(d[x]<d[y])
        y=fa[y];
    while(x!=y)
        x=fa[x],y=fa[y];
    return x;
}
void dfs(int x)
{
    for(auto y:e[x])
    {
        if(y==fa[x])continue;
        fa[y]=x;
        d[y]=d[x]+1;
        dfs(y);
    }
}
void work(int d)
{
    if(d==n+1)
    {
        if(a.size()==0)return ;
        int t=a[0];
        for(auto x:a)
            t=lca(x,t);
        if(a.size()&1)
            sum[t]++;
        else
            sum[t]--;
        return ;
    }
    a.push_back(d);
    work(d+1);
    a.pop_back();
    work(d+1); 
}
int main()
{
    n=read();
    for(int i=1;i<n;i++)
    {
        int x=read(),y=read();
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(1);
    work(1);
    for(int i=1;i<=n;i++)
        cout<<sum[i]<<' ';
}
找規律

可以ac的代碼(大概:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read()
{
    ll x;scanf("%lld",&x);return x;
}
int n;
ll sum[200010],ans;
int main()
{
    n=read();
    for(int i=1;i<n;i++)
        sum[read()]--;
    for(int i=1;i<=n;i++)
        ans+=(1-sum[i])*read();
    cout<<ans;
}
C

 

 L

二維前綴和板子題

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read() {
    ll x;
    scanf("%lld",&x);
    return x;
}
int n,m,k,sum[4][1010][1010];
int a,b,c,d;
char s[1010];
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=m;j++)
        {
            sum[1][i][j]=sum[1][i-1][j]+sum[1][i][j-1]-sum[1][i-1][j-1]+(s[j]=='C');
            sum[2][i][j]=sum[2][i-1][j]+sum[2][i][j-1]-sum[2][i-1][j-1]+(s[j]=='M');
            sum[3][i][j]=sum[3][i-1][j]+sum[3][i][j-1]-sum[3][i-1][j-1]+(s[j]=='F');
        }
    }
    for(;k;k--)
    {
        a=read();b=read();c=read();d=read();
        for(int i=1;i<=3;i++)
            printf("%d ",sum[i][c][d]-sum[i][c][b-1]-sum[i][a-1][d]+sum[i][a-1][b-1]);
        printf("\n");
    }
}
L

 

 

M

理解題意後發現只需要對每個商家的物品從大到小排序,選前第i大的物品做揹包,體積是i,假價值是(Σai)-X。f[i][j]表示前i個商家用j個物品最多賣多少錢。複雜度m*n+n*n

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read() {
    ll x;
    scanf("%lld",&x);
    return x;
}
int n,m,k;
int x[1010],f[1010][1010];
vector<int>a[1010];
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=m;i++)
        x[i]=read();
    for(int i=1;i<=n;i++)
    {
        int v=read();
        a[read()].push_back(v);
    }
    for(int i=1;i<=k;i++)
        f[0][i]=-1e9;
    for(int i=1;i<=m;i++)
    {
        for(int kk=1;kk<=k;kk++)
            f[i][kk]=f[i-1][kk];
        sort(a[i].begin(),a[i].end(),greater<int>());
        for(int j=0,cnt=1,sum=0;j<a[i].size();j++,cnt++)
        {
            sum+=a[i][j];
            for(int kk=k;kk>=cnt;kk--)
                f[i][kk]=max(f[i][kk],f[i-1][kk-cnt]+sum-x[i]);
        }
    }
    cout<<f[m][k];
}
M

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章