【loli的胡策】NOIP训练10.2(快速幂+树形期望dp)

T1:

这里写图片描述

题解:

我们发现在放字母的时候,第一位可以放m种,第二位只能放m-1种,第三位只能放m-2种,被前两位所限制,后面的也只能放m-2种,快速幂不解释
考试的时候不知道怎么想的觉得n是10^18会卡快速幂,然后就不想要最后10pts
其实把ksm的k设成longlong就A了。。。。。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#define LL long long
using namespace std;
const int Mod=1e9+7;
LL ksm(LL a,LL k)
{
    LL ans=1;a%=Mod;
    for (;k;k>>=1,a=a*a%Mod)
      if (k&1) ans=ans*a%Mod;
    return ans%Mod;
}
int main()
{
    freopen("anti.in","r",stdin);
    freopen("anti.out","w",stdout);
    int T,i,j,k;LL n,m;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld%lld",&n,&m);
        m%=Mod;
        if (n==1){printf("%lld\n",m);continue;}
        LL lj=m*(m-1)%Mod;
        printf("%lld\n",ksm(m-2,n-2)*lj%Mod);
    }
}

T2:

这里写图片描述

题解:

其实就是树形dp,当时确实想的要dp,但是打了50pts就放那里了,后来也没细想
qu[i]表示儿子i的期望值;sum[i]表示所有儿子的期望和;g[i]表示i节点当根节点的时候的值

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#define INF 1e9
#define N 1000005
using namespace std;
int tot,nxt[N*2],point[N],v[N*2],a[N],out[N],father[N];
double qu[N],sum[N],g[N];
void addline(int x,int y)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; out[x]++;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; out[y]++;
}
void dfs(int x,int fa)
{
    father[x]=fa;
    qu[x]=a[x];
    if (out[x]==1 && x!=1) return;
    for (int i=point[x];i;i=nxt[i]) 
      if (v[i]!=fa)
      {
        dfs(v[i],x);
        sum[x]+=qu[v[i]];//儿子的期望和 
      }
    if (x!=1) qu[x]+=sum[x]/(double)(out[x]-1);
    else qu[x]+=sum[x]/(double)out[x];
}
void work(int x,double up)
{
    for (int i=point[x];i;i=nxt[i])
      if (v[i]!=father[x])
      {
        double zoom;
        if (out[x]>1) zoom=(sum[x]-qu[v[i]]+up)/(double)(out[x]-1)+a[x];else zoom=a[x];  
        g[v[i]]=(sum[v[i]]+zoom)/out[v[i]]+a[v[i]];
        work(v[i],zoom);
      }
}
int main()
{
    freopen("walking.in","r",stdin);
    freopen("walking.out","w",stdout);
    int n,i,j;
    scanf("%d",&n);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    for (i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        addline(x,y);
    }
    dfs(1,0); g[1]=qu[1];
    work(1,0);
    int k=1;
    for (i=2;i<=n;i++) if (g[k]>g[i]) k=i;
    printf("%d",k);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值