ZF_20160614_计蒜客

来源:互联网 发布:linux 登录日志查询 编辑:程序博客网 时间:2024/06/15 21:31

初赛一 青云的机房组网方案
求所有互质节点距离和
1、树形dp
2、质因数的容斥原理
例如i为24,只需要考虑1,2,3,6
i为45,只需要考虑1,3,5,15

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define ll long long#define clr(x,y) memset(x,y,sizeof x)using namespace std;ll pri[510],vis[510],lim=500,pnt;ll tag[510],tnt,F[510];vector<ll>Div[510],Mul[510];void dfs(ll cur,ll id,ll flag){    if(id>pnt)return;    dfs(cur,id+1,flag);    if(cur*pri[id]<=lim)    {        tag[++tnt]=cur*pri[id];        F[cur*pri[id]]=-flag;        dfs(cur*pri[id],id+1,-flag);    }}void getP(){    for(ll i=2;i<=lim;i++)    {        if(!vis[i])        {            pri[++pnt]=i;            for(ll j=2;i*j<=lim;j++)vis[i*j]=1;        }    }    tag[++tnt]=1;F[1]=1;    dfs(1,1,1);    sort(tag+1,tag+tnt+1);    for(ll i=1;i<=tnt;i++)    {        for(ll j=1;j*tag[i]<=lim;j++)        {            Div[j*tag[i]].push_back(tag[i]);            Mul[tag[i]].push_back(j*tag[i]);        }    }}ll n,dat[10010],ans;ll tot[510],left[10010][510],right[10010][510];ll sum[10010][510];namespace G{    vector<ll>V[10010];    ll mx;    void Init()    {        for(ll i=1;i<=n;i++)V[i].clear();        clr(tot,0);clr(left,0);clr(sum,0);        ans=0;mx=0;    }    void dfs(ll u,ll fa)    {        left[u][dat[u]]++;        ll len=V[u].size();        for(ll i=0;i<len;i++)        {            ll v=V[u][i];            if(v==fa)continue;            dfs(v,u);            for(ll j=1;j<=mx;j++)left[u][j]+=left[v][j];        }        for(ll i=1;i<=tnt;i++)        {            for(int j=1;j*tag[i]<=lim;j++)                sum[u][tag[i]]+=left[u][j*tag[i]];        }        for(ll i=1;i<=mx;i++)right[u][i]=tot[i]-left[u][i];        for(ll i=1;i<=mx;i++)        {            ll siz=Div[i].size();            for(ll j=0;j<siz;j++)            {                ans+=sum[u][Div[i][j]]*F[Div[i][j]]*right[u][i];            }        }    }    void Go()    {        while(~scanf("%lld",&n))        {            Init();            for(ll i=1;i<=n;i++)scanf("%lld",&dat[i]),mx=mx>dat[i]?mx:dat[i],tot[dat[i]]++;            for(ll i=1;i<n;i++)            {                ll x,y;                scanf("%lld%lld",&x,&y);                V[x].push_back(y);V[y].push_back(x);            }            dfs(1,-1);            printf("%lld\n",ans);        }    }}int main(){    getP();    G::Go();}

初赛二 联想的显示屏校准
计算几何

初赛三 百度帐号的选取方案
输入用户名abc,如果重复就变成abcabc,求不重复时循环节最小是多少?

KMP
1、val[i][j] 从i到j的最大循环节
2、num[i][j] i开始循环节为j的子串有几个
3、sum[i][j] num数组的后缀和

#include<cstdio>#include<cstring>#include<algorithm>#define ll long long#define clr(x,y) memset(x,y,sizeof x)using namespace std;ll val[1010][1010],num[1010][1010],sum[1010][1010];namespace KMP{    ll nxt[100010];    ll gnt(char b[],ll lb)    {        for(ll i=0,j=nxt[0]=-1;i<lb;)        {            j==-1||b[i]==b[j]?            nxt[++i]=++j:j=nxt[j];        }    }};char c[1010];int main(){    while(~scanf("%s",c+1))    {        ll len=strlen(c+1);        clr(val,0);        clr(num,0);        clr(sum,0);        for(ll i=1;i<=len;i++)        {            KMP::gnt(c+i,len+1-i);            for(ll j=i;j<=len;j++)            {                val[i][j]=(j-i+1)%((j-i+1)-KMP::nxt[j-i+1])==0?(j-i+1)/((j-i+1)-KMP::nxt[j-i+1]):1;                num[i][val[i][j]]++;            }        }        for(ll i=len;i>0;i--)        {            for(ll j=1;j<=len;j++)                sum[i][j]=sum[i+1][j]+num[i][j];        }        ll ans=0;        for(ll i=1;i<=len;i++)        {            for(ll j=i;j<=len;j++)                ans+=sum[j+1][val[i][j]];        }        printf("%lld\n",ans);    }}

初赛四 遗失的支付宝密码
1、容斥 f(x)表示至少含有x个square的字符串的个数
结果为c1*m^1 + c2*m^2+ … + cn*m^n
2、打表 电脑大概需要跑20秒左右
3、要求前缀和,因为字符串长度要求不大于n,1,2也要算
4、用unsigned long long比较好

#include<cstdio>#include<cstring>#include<algorithm>#define ll unsigned long longusing namespace std;const ll mod=(ll)1<<32;ll tab[50][50]={{0},{0,1},{0,-1,1},{0,0,-1,1},{0,1,-1,-1,1},{0,0,1,-1,-1,1},{0,0,1,0,-1,-1,1},{0,0,0,1,0,-1,-1,1},{0,-1,1,1,0,0,-1,-1,1},{0,0,-1,1,1,0,0,-1,-1,1},{0,-1,0,0,2,0,0,0,-1,-1,1},{0,0,-1,0,0,2,0,0,0,-1,-1,1},{0,0,-1,-1,1,1,1,0,0,0,-1,-1,1},{0,0,0,-1,-1,1,1,1,0,0,0,-1,-1,1},{0,0,-1,0,-1,0,2,0,1,0,0,0,-1,-1,1},{0,0,0,-1,0,-1,0,2,0,1,0,0,0,-1,-1,1},{0,2,-3,0,-1,0,0,1,1,0,1,0,0,0,-1,-1,1},{0,0,2,-3,0,-1,0,0,1,1,0,1,0,0,0,-1,-1,1},{0,1,0,0,-3,0,-1,1,1,0,1,0,1,0,0,0,-1,-1,1},{0,0,1,0,0,-3,0,-1,1,1,0,1,0,1,0,0,0,-1,-1,1},{0,2,-1,0,-1,0,-3,0,0,2,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,2,-1,0,-1,0,-3,0,0,2,0,0,1,0,1,0,0,0,-1,-1,1},{0,2,1,-1,-1,-1,-1,0,-3,1,1,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,2,1,-1,-1,-1,-1,0,-3,1,1,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,1,1,2,-1,-1,-2,-1,-1,0,-2,2,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,1,1,2,-1,-1,-2,-1,-1,0,-2,2,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,1,2,0,0,1,-1,-2,-2,-1,-1,1,-1,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,1,2,0,0,1,-1,-2,-2,-1,-1,1,-1,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,3,1,0,0,-1,1,-2,-2,-2,-1,0,2,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,0,3,1,0,0,-1,1,-2,-2,-2,-1,0,2,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,2,1,2,0,0,-1,-1,0,-2,-2,-2,0,1,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,0,2,1,2,0,0,-1,-1,0,-2,-2,-2,0,1,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,-3,6,1,1,-1,2,0,-1,-1,-2,0,-2,-2,-1,1,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,-3,6,1,1,-1,2,0,-1,-1,-2,0,-2,-2,-1,1,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,-2,2,1,6,-1,0,-1,2,-1,-1,-2,-2,0,-2,-1,0,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,-2,2,1,6,-1,0,-1,2,-1,-1,-2,-2,0,-2,-1,0,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,-4,4,0,4,0,5,-2,0,-1,1,-1,-2,-2,-2,0,-1,0,-1,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,-4,4,0,4,0,5,-2,0,-1,1,-1,-2,-2,-2,0,-1,0,-1,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,-4,4,-2,5,1,2,0,4,-2,0,-2,1,-2,-2,-2,-2,1,0,-1,-1,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,0,-4,4,-2,5,1,2,0,4,-2,0,-2,1,-2,-2,-2,-2,1,0,-1,-1,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1},{0,-7,7,-3,6,-2,5,0,2,-1,4,-2,-1,-2,0,-2,-2,-2,-1,2,-1,-1,-1,0,0,1,-2,1,0,1,0,0,1,0,1,0,0,0,-1,-1,1}};ll pow(ll p,ll q){    ll ret=1;    while(q)    {        if(q&1)        {            ret*=p;ret%=mod;        }        q>>=1;        p=p*p%mod;    }    return ret;}int main(){    for(ll i=1;i<=40;i++)    {        for(ll j=0;j<=i;j++)tab[i][j]+=tab[i-1][j],tab[i][j]=(tab[i][j]%mod+mod)%mod;    }    ll n,m;    while(~scanf("%lld%lld",&n,&m))    {        ll ans=0;        for(ll j=0;j<=n;j++)ans+=(tab[n][j]*pow(m,j))%mod,ans%=mod;        printf("%lld\n",ans);    }}

初赛五 腾讯的新游戏
勇士挑战恶魔,恶魔有n队,每队mi个
q次换防,i队前几个与j队前几个互换
1、链表实现换防
2、逐一计算攻击每队的所需防御力
3、按照防御力从小到大排序,贪心即可

初赛六
1、树形dp f[u][color]
2、再次考到容斥原理
3、dfs的复杂度是O(n)的!dfs的复杂度是O(n)!的dfs的复杂度是O(n)的!当时没想到这一点,不敢枚举最大最小值

#include<cstdio>#include<cstring>#include<vector>#define ll long long#define D(x) ((x)>-(x)?(x):-(x))using namespace std;const ll inf=1e15;ll dat[110][2],n;ll a[110],b[110],top;namespace G{    vector<ll>V[110];    ll f[110][2];    void dfs(ll u,ll fa)    {        ll len=V[u].size();        for(ll i=0;i<len;i++)        {            ll v=V[u][i];            if(v==fa)continue;            dfs(v,u);        }        ll node; if(u==1)node=len;else node=len-1;        if(node==0)        {            f[u][0]=dat[u][0];f[u][1]=dat[u][1];return;        }        if(node==1)        {            ll v;for(ll i=0;i<len;i++)if(V[u][i]!=fa)v=V[u][i];            f[u][0]=max(dat[u][0]+f[v][0]-(D(dat[u][0]-dat[v][0])+999)/1000*666*u,                        dat[u][0]+f[v][1]-(D(dat[u][0]-dat[v][1])+999)/1000*666*u);            f[u][1]=max(dat[u][1]+f[v][0]-(D(dat[u][1]-dat[v][0])+999)/1000*666*u,                        dat[u][1]+f[v][1]-(D(dat[u][1]-dat[v][1])+999)/1000*666*u);            return;        }        f[u][0]=f[u][1]=-inf;        ll mx,mi,mxf,mif;        for(ll i=0;i<len;i++)//第一个点        {            ll t1=V[u][i];if(t1==fa)continue;            for(ll c1=0;c1<2;c1++)            {                for(ll j=i+1;j<len;j++)//第二个点                {                    ll t2=V[u][j];if(t2==fa)continue;                    for(ll c2=0;c2<2;c2++)                    {                        for(ll c0=0;c0<2;c0++)//u点                        {                            if(dat[t1][c1]>dat[t2][c2])                                mx=dat[t1][c1],mxf=f[t1][c1],mi=dat[t2][c2],mif=f[t2][c2];                            else                                mi=dat[t1][c1],mif=f[t1][c1],mx=dat[t2][c2],mxf=f[t2][c2];                            mx=max(mx,dat[u][c0]);                            mi=min(mi,dat[u][c0]);                            ll ret=dat[u][c0]+mxf+mif-(mx-mi+999)/1000*666*u;                            ll flag=1;                            for(ll l=0;l<len;l++)if(l-i&&l-j)//其他点                            {                                ll t3=V[u][l];if(t3==fa)continue;                                ll tmp=-inf;                                if(mi<=dat[t3][0]&&dat[t3][0]<=mx)tmp=max(tmp,f[t3][0]);                                if(mi<=dat[t3][1]&&dat[t3][1]<=mx)tmp=max(tmp,f[t3][1]);                                if(tmp==-inf)                                {                                    flag=0;break;                                }                                else ret+=tmp;                            }                            if(flag)f[u][c0]=max(f[u][c0],ret);                        }                    }                }            }        }    }    void Go()    {        while(~scanf("%lld",&n))        {            for(ll i=1;i<=n;i++)scanf("%lld%lld",&dat[i][0],&dat[i][1]),V[i].clear();            for(ll i=1;i<n;i++)            {                ll x,y;                scanf("%lld%lld",&x,&y);                V[x].push_back(y);                V[y].push_back(x);            }            dfs(1,-1);            printf("%lld\n",max(f[1][0],f[1][1]));        }    }}int main(){    G::Go();}
0 0
原创粉丝点击