zoukankan      html  css  js  c++  java
  • 训练日志9 (7.31)

    T1 辣鸡(ljh)

      又是一道模拟题,我们所要做的就是用简单的$for$循环把各种情况枚举出来,暴力计算答案,就能A了,复杂度$O(n^2)$(其实也不严格,中间有一些小减枝)。

      在这道题中,具体的,我们可以把每个无重叠格子对答案的贡献看成两部分:

    1. 方块内部的贡献。
    2. 方块间的贡献。

      这时候问题就被简化了。

      方格内部的贡献,我们可以转化成一个神奇的公式:$ res_i=(lenx-1) imes (leny-1) $(当时我是没想出来,直接暴力加)。

      然后计算之间贡献,之间的贡献只与最外层的一条边有关,所以枚举每一个块,计算他们两个之间块的贡献即可,不再细说。

      可是这样会$TLE$,我们应该想一个强力一点的剪枝。

      我们可以$sort$一下方块,使他们的横坐标升序排列,因此便得到了:只要当前节点的右端小于比较节点的左端-1,那之后的所有点都不再跟当前节点接触,直接$break$。

      那么这道题就完美的解决了,复杂度$O(n^2)$,比较简单的一道题。

      小弟不才。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #define int long long
     5 #define HZOI using namespace std
     6 HZOI;
     7 struct node{
     8     int lx,ly,rx,ry,dx,dy;
     9     friend bool operator < (node a,node b)
    10     {
    11         return (a.lx^b.lx)?a.lx<b.lx:a.ly<b.ly;
    12     }
    13 }kuai[100003];
    14 int n,ans1,ans2;
    15 inline int min(int a,int b) { return a<b?a:b; }
    16 inline int max(int a,int b) { return a>b?a:b; }
    17 signed main()
    18 {
    19     scanf("%lld",&n);
    20     for (int i=1,lx,ly,rx,ry; i<=n; ++i)
    21     {
    22         scanf("%lld%lld%lld%lld",&lx,&ly,&rx,&ry);
    23         int dx=rx-lx+1,dy=ry-ly+1,res=0;
    24         kuai[i].lx=lx,kuai[i].rx=rx,kuai[i].ly=ly,kuai[i].ry=ry;
    25         kuai[i].dx=dx,kuai[i].dy=dy;
    26 /*        for (int j=1; j<min(dy,dx); ++j)
    27             res+=j;
    28         ans1+=(res<<1);
    29         ans1+=(max(dy,dx)-min(dy,dx)-1)*min(dy-1,dx-1);*/
    30         ans1+=(dx-1)*(dy-1);
    31     }
    32     ans1<<=1;
    33     sort(kuai+1,kuai+n+1);
    34     for (int i=1; i<=n; ++i)
    35     {
    36         int ux=kuai[i].dx,uy=kuai[i].dy;
    37         int ux1=kuai[i].lx,ux2=kuai[i].rx,uy1=kuai[i].ly,uy2=kuai[i].ry;
    38         for (int j=i+1; j<=n; ++j)
    39         {        
    40             int vx=kuai[j].dx,vy=kuai[j].dy;
    41             int vx1=kuai[j].lx,vx2=kuai[j].rx,vy1=kuai[j].ly,vy2=kuai[j].ry;
    42             if (ux2<vx1-1) break;
    43             if (uy2==vy1-1 or uy1==vy2+1)
    44             {
    45                 if (vx1<ux1 and vx2>ux2)
    46                     {ans2+=(ux<<1);}
    47                 else if (vx1>ux1 and vx2<ux2)
    48                     {ans2+=(vx<<1);}
    49                 else if (ux1>vx2+1 or ux2<vx1-1) continue;
    50                 else if (ux1==vx2+1) ++ans2;
    51                 else if (ux2==vx1-1) ++ans2;
    52                 else 
    53                 {
    54                     int jiao=min(ux2-vx1+1,vx2-ux1+1);
    55                     ans2+=(jiao<<1);
    56                     if (ux1==vx1) --ans2;
    57                     if (ux2==vx2) --ans2;
    58                 }
    59             }
    60             else if (ux2==vx1-1 or ux1==vx2+1)
    61             {
    62                 if (vy1<uy1 and vy2>uy2)
    63                     {ans2+=(uy<<1);}
    64                 else if (vy1>uy1 and vy2<uy2)
    65                     {ans2+=(vy<<1);}
    66                 else if (uy1>vy2+1 or uy2<vy1-1) continue;
    67                 else if (uy1==vy2+1) ++ans2;
    68                 else if (uy2==vy1-1) ++ans2;
    69                 else 
    70                 {
    71                     int jiao=min(uy2-vy1+1,vy2-uy1+1);
    72                     ans2+=(jiao<<1);
    73                     if (uy1==vy1) --ans2;
    74                     if (uy2==vy2) --ans2;
    75                 }
    76             }
    77         }
    78     }
    79     printf("%lld
    ",ans1+ans2);
    80     return 0;
    81 }
    辣鸡(ljh)

     

    T2 模板(ac)

      挺难的一道题,实力最多拿到70

      很容易看出来这道题是一颗线段树,因为之前也做过一道类似的题。

      也是之前的那道题救了我,让我很快的想到了线段树合并。

      不过这道题肯定不是线段树合并,但是可以得到40分,加上暴力可以得到的30分,已经是考试极限了。

      1 #include<cstdio>
      2 #include<set>
      3 #include<iostream>
      4 #include<algorithm>
      5 #define int long long
      6 #define HZOI using namespace std
      7 HZOI;
      8 const int MAXN=1e6+3;
      9 struct node{
     10     int lc,rc,num;
     11 }tr[MAXN<<5];
     12 int n,m,Q,cnt;
     13 int tt,vv[MAXN<<1],nx[MAXN<<1],first[MAXN];
     14 int qk[MAXN],qnum[MAXN],a[MAXN],ans[MAXN];
     15 int w[MAXN];
     16 int head,tail,q[MAXN],fa[MAXN],vis[MAXN];
     17 int num[MAXN];
     18 set<int> s[MAXN];
     19 void Bfs(int );
     20 void Dfs(int ,int );
     21 void Insert(int &,int ,int ,int );
     22 int Merge(int ,int );
     23 inline void Add(int ,int );
     24 inline int read();
     25 signed main()
     26 {
     27     scanf("%lld",&n);
     28     cnt=n;
     29     for (int i=1,x,y; i<n; ++i)
     30     {
     31         scanf("%lld%lld",&x,&y);
     32         Add(x,y); Add(y,x);
     33     }
     34     if (n<=1000 and m<=1000)
     35     {
     36         Bfs(1);
     37         for (int i=1; i<=n; ++i)
     38             scanf("%lld",&w[i]);
     39         scanf("%lld",&m);
     40         for (int i=1; i<=m; ++i)
     41             scanf("%lld%lld",&qk[i],&qnum[i]),a[i]=qnum[i];
     42         sort(a+1,a+1+m);
     43         int lena=unique(a+1,a+1+m)-a-1;
     44         for (int i=1; i<=m; ++i)
     45             qnum[i]=lower_bound(a+1,a+lena+1,qnum[i])-a;
     46         for (int i=1; i<=m; ++i)
     47         {
     48             int to=qk[i],data=qnum[i];
     49             while (to)
     50             {
     51                 if (w[to] and s[to].find(data)!=s[to].end()) --w[to];
     52                 if (w[to] and s[to].find(data)==s[to].end()) ++num[to],s[to].insert(data),--w[to];
     53                 to=fa[to];
     54             }
     55         }
     56         scanf("%lld",&Q);
     57         for (int i=1,x; i<=Q; ++i)
     58         {
     59             scanf("%lld",&x);
     60             printf("%lld
    ",num[x]);
     61         }
     62     }
     63     else 
     64     {
     65         for (int i=1; i<=n; ++i)
     66             scanf("%lld",&w[i]);
     67         scanf("%lld",&m);
     68         for (int i=1; i<=m; ++i)
     69             scanf("%lld%lld",&qk[i],&qnum[i]),a[i]=qnum[i];
     70         sort(a+1,a+1+m);
     71         int lena=unique(a+1,a+1+m)-a-1;
     72         for (int i=1; i<=m; ++i)
     73             qnum[i]=lower_bound(a+1,a+lena+1,qnum[i])-a;
     74         for (int i=1; i<=m; ++i)
     75             Insert(qk[i],1,lena,qnum[i]);
     76         Dfs(1,0);
     77         scanf("%lld",&Q);
     78         for (int i=1,x; i<=Q; ++i)
     79         {
     80             scanf("%lld",&x);
     81             printf("%lld
    ",tr[x].num);
     82         }
     83     }
     84     return 0;
     85 }
     86 void Insert(int &k,int l,int r,int data)
     87 {
     88     if (!k) k=++cnt;
     89     if (l==r) { tr[k].num=1; return ; }
     90     int mid=l+r>>1;
     91     if (data<=mid) Insert(tr[k].lc,l,mid,data);
     92     else Insert(tr[k].rc,mid+1,r,data);
     93     tr[k].num=tr[tr[k].lc].num+tr[tr[k].rc].num;
     94 }
     95 int Merge(int x,int y)
     96 {
     97     if (!x or !y) return x+y;
     98     tr[x].lc=Merge(tr[x].lc,tr[y].lc);
     99     tr[x].rc=Merge(tr[x].rc,tr[y].rc);
    100     if (!tr[x].lc and !tr[x].rc) return x;
    101     tr[x].num=tr[tr[x].lc].num+tr[tr[x].rc].num;
    102     return x;
    103 }
    104 void Dfs(int k,int father)
    105 {
    106     for (int i=first[k]; i; i=nx[i])
    107     {
    108         if (vv[i]==father) continue;
    109         Dfs(vv[i],k);
    110         Merge(k,vv[i]);
    111     }
    112 }
    113 void Bfs(int k)
    114 {
    115     head=tail=0;
    116     q[++tail]=k;
    117     fa[k]=0;
    118     vis[k]=1;
    119     while (head^tail)
    120     {
    121         int x=q[++head];
    122         for (int i=first[x]; i; i=nx[i])
    123         {
    124             int ver=vv[i];
    125             if (vis[ver]) continue;
    126             fa[ver]=x;
    127             q[++tail]=ver;
    128             vis[ver]=1;
    129         }
    130     }
    131 }
    132 inline void Add(int u,int v)
    133 {
    134     vv[++tt]=v; nx[tt]=first[u]; first[u]=tt;
    135 }
    136 inline int read()
    137 {
    138     int num=0; char ch=getchar();
    139     while (ch<'0' or ch>'9') ch=getchar();
    140     while (ch>='0' and ch<='9') num=(num<<3)+(num<<1)+(ch^48),ch=getchar();
    141     return num;
    142 }
    30+40

      这道题好在它的思路不同以往普通线段树,它更新了我对线段树维护信息的认识。

      这道题以操作时间为坐标轴,并以之为基础建立线段树,通过操作的不同顺序来维护所需要的信息。

      这个思路很棒啊,考试的时候真的想不到。

      那么该怎么操作呢?

      我们开很多很多个$vector$,来存在某个节点的操作的颜色及时间。

      大体思路就是找到最深层的叶子节点,然后逐层向上合并,最后合并至根节点,期间维护各种信息,使答案合法。

      先插一下合并方法:线段树合并在这里肯定不好使,它合并的很快,但是只能将两颗线段树上的对应位置合并在一起,而无法判断子树之间的影响,因此它不再适用。所以我们选择一种相对暴力的方法,启发式合并(名字好高端,但其实很暴力),思想就是把大的插入到小的里边,怎么插?取出树中的所有信息,暴力插!

      以为要把小的塞进大的里,所以我们要找到每一个节点的最大子树,称它为重儿子,然后进行$DFS$。

      这里面,我们显然需要记录某个元素是否在比他更早的时间里出现过,用到了桶,可是桶很难受,它不能开到二维的数据范围$1e5$,所以我们有用到了一个小思想,把桶重复利用,每操作完一个节点就把其中的信息全部清空,注意,这里复杂度可能不好把握,一定不能用$memset$用多少删多少,这样才可以让时间复杂度有保障。

      我们的操作大多进行在$vector$中,统计答案只需要把$vector$中的元素一个个插入线段树中,最后访问,就可以了。

      注意这种算法,每一个更新到的字节点最后他们的桶都要清空

      $TLE 30$。

      1 #include<cstdio>
      2 #include<vector>
      3 #include<iostream>
      4 #include<algorithm>
      5 #define int long long
      6 #define HZOI using namespace std
      7 HZOI;
      8 const int MAXN=5e6+3;
      9 struct node{
     10     int lc,rc,num,sum;
     11 }tr[MAXN<<3];
     12 int n,m,Q,cnt;
     13 int tt,vv[MAXN<<1],nx[MAXN<<1],first[MAXN];
     14 int qk[MAXN],qnum[MAXN],a[MAXN],sze[MAXN],hea[MAXN];
     15 int w[MAXN],ans[MAXN],t[MAXN],root[MAXN];
     16 vector<pair<int ,int > > vec[MAXN];
     17 void Dfs(int ,int );
     18 void Dfss(int ,int );
     19 void Insert(int &,int ,int ,int ,int ,int );
     20 int Ask(int ,int ,int ,int );
     21 void Merge(int ,int );
     22 inline void Add(int ,int );
     23 inline int read();
     24 signed main()
     25 {
     26     scanf("%lld",&n);
     27     for (int i=1,x,y; i<n; ++i)
     28     {
     29         scanf("%lld%lld",&x,&y);
     30         Add(x,y); Add(y,x);
     31     }
     32     for (int i=1; i<=n; ++i)
     33         scanf("%lld",&w[i]);
     34     scanf("%lld",&m);
     35     for (int i=1; i<=m; ++i)
     36         scanf("%lld%lld",&qk[i],&qnum[i]),a[i]=qnum[i];
     37     sort(a+1,a+1+m);
     38     int lena=unique(a+1,a+1+m)-a-1;
     39     for (int i=1; i<=m; ++i)
     40         qnum[i]=lower_bound(a+1,a+lena+1,qnum[i])-a;
     41     for (int i=1; i<=m; ++i)
     42         vec[qk[i]].push_back(make_pair(i,qnum[i]));
     43     Dfs(1,0);
     44     Dfss(1,0);
     45     scanf("%lld",&Q);
     46     for (int i=1; i<=Q; ++i)
     47         printf("%lld
    ",ans[read()]);
     48     return 0;
     49 }
     50 void Dfss(int k,int father)
     51 {
     52     for (int i=first[k]; i; i=nx[i])
     53     {
     54         int ver=vv[i];
     55         if (ver==father or ver==hea[k]) continue;
     56         Dfss(ver,k);
     57         for (int j=0; j<vec[ver].size(); ++j)
     58             t[vec[ver][j].second]=0;
     59     }
     60     if (hea[k]) 
     61     {
     62         Dfss(hea[k],k); 
     63         for (int j=0; j<vec[hea[k]].size(); ++j)
     64             t[vec[hea[k]][j].second]=0;
     65         Merge(hea[k],k); 
     66         swap(vec[hea[k]],vec[k]);
     67     }
     68     for (int i=first[k]; i; i=nx[i])
     69     {
     70         int ver=vv[i];
     71         if (ver==father or ver==hea[k]) continue;
     72         Merge(k,ver);
     73     }
     74     for (int i=0; i<vec[k].size(); ++i)
     75     {
     76         int time=vec[k][i].first,color=vec[k][i].second;
     77         if (!t[color]) Insert(root[k],1,m,time,1,0),t[color]=time;
     78         else if (t[color]>time)
     79         {
     80             Insert(root[k],1,m,time,1,0);
     81             Insert(root[k],1,m,t[color],-1,0);
     82             t[color]=time;
     83         }
     84         Insert(root[k],1,m,time,0,1);
     85     }
     86     ans[k]=Ask(root[k],1,m,w[k]);
     87 }
     88 int Ask(int k,int l,int r,int weight)
     89 {
     90     if (weight<=0) return 0;
     91     if (l==r) return tr[k].num;
     92     int mid=l+r>>1,res=0;
     93     if (tr[tr[k].lc].sum<=weight)
     94     {
     95         res+=tr[tr[k].lc].num;
     96         res+=Ask(tr[k].rc,mid+1,r,weight-tr[tr[k].lc].sum);
     97         return res;
     98     }
     99     else res=Ask(tr[k].lc,l,mid,weight);
    100     return res;
    101 }
    102 void Insert(int &k,int l,int r,int goal,int col,int que)
    103 {
    104     if (!k) k=++cnt;
    105     if (l==r) 
    106     {
    107         tr[k].sum+=que; tr[k].num+=col;
    108         return ;
    109     }
    110     int mid=l+r>>1;
    111     if (goal<=mid) Insert(tr[k].lc,l,mid,goal,col,que);
    112     else Insert(tr[k].rc,mid+1,r,goal,col,que);
    113     tr[k].num=tr[tr[k].lc].num+tr[tr[k].rc].num;
    114     tr[k].sum=tr[tr[k].lc].sum+tr[tr[k].rc].sum;
    115 }
    116 void Merge(int x,int y)
    117 {
    118     for (int i=0; i<vec[y].size(); ++i)
    119         vec[x].push_back(vec[y][i]);
    120     vec[y].clear();
    121 }
    122 void Dfs(int k,int father)
    123 {
    124     for (int i=first[k]; i; i=nx[i])
    125     {
    126         if (vv[i]==father) continue;
    127         Dfs(vv[i],k);
    128         if (sze[vv[i]]>sze[hea[k]]) hea[k]=vv[i];
    129         sze[k]+=sze[vv[i]];
    130     }
    131     ++sze[k];
    132 }
    133 inline void Add(int u,int v)
    134 {
    135     vv[++tt]=v; nx[tt]=first[u]; first[u]=tt;
    136 }
    137 inline int read()
    138 {
    139     int nn=0; int ch=getchar();
    140     while (ch<'0' or ch>'9') ch=getchar();
    141     while (ch>='0' and ch<='9') nn=(nn<<3)+(nn<<1)+(ch^48),ch=getchar();
    142     return nn;
    143 }
    TLE 30

      接下来才是真正的正解。

      我们发现把每一个重儿子的桶都清空,太多了,时间根本接受不了,怎么办?

      想一下我们为什么要选择重儿子作为基树。

      重儿子的子树比较大,这正是我们保证时间复杂度的要求。

      那么我们只要将重儿子的信息一层一层往上传上去,将重儿子的信息传到父节点上不就好了么。

      因此,只要父节点k有重儿子,我们就把它的$root$置成重儿子的$root$,然后在k这颗树上进行操作,最后将重儿子信息整合到k上,结束了。

      注意不要直接将重儿子插到$k$上,要利用$vector$的交换方式。

      小弟不才。

      1 #include<cstdio>
      2 #include<vector>
      3 #include<iostream>
      4 #include<algorithm>
      5 #define int long long
      6 #define HZOI using namespace std
      7 HZOI;
      8 const int MAXN=5e6+3;
      9 struct node{
     10     int lc,rc,num,sum;
     11 }tr[MAXN<<3];
     12 int n,m,Q,cnt;
     13 int tt,vv[MAXN<<1],nx[MAXN<<1],first[MAXN];
     14 int qk[MAXN],qnum[MAXN],a[MAXN],sze[MAXN],hea[MAXN];
     15 int w[MAXN],ans[MAXN],t[MAXN],root[MAXN];
     16 vector<pair<int ,int > > vec[MAXN];
     17 void Dfs(int ,int );
     18 void Dfss(int ,int );
     19 void Insert(int &,int ,int ,int ,int ,int );
     20 int Ask(int ,int ,int ,int );
     21 void Merge(int ,int );
     22 inline void Add(int ,int );
     23 inline int read();
     24 signed main()
     25 {
     26     scanf("%lld",&n);
     27     for (int i=1,x,y; i<n; ++i)
     28     {
     29         scanf("%lld%lld",&x,&y);
     30         Add(x,y); Add(y,x);
     31     }
     32     for (int i=1; i<=n; ++i)
     33         scanf("%lld",&w[i]);
     34     scanf("%lld",&m);
     35     for (int i=1; i<=m; ++i)
     36         scanf("%lld%lld",&qk[i],&qnum[i]),a[i]=qnum[i];
     37     sort(a+1,a+1+m);
     38     int lena=unique(a+1,a+1+m)-a-1;
     39     for (int i=1; i<=m; ++i)
     40         qnum[i]=lower_bound(a+1,a+lena+1,qnum[i])-a;
     41     for (int i=1; i<=m; ++i)
     42         vec[qk[i]].push_back(make_pair(i,qnum[i]));
     43     Dfs(1,0);
     44     Dfss(1,0);
     45     scanf("%lld",&Q);
     46     for (int i=1; i<=Q; ++i)
     47         printf("%lld
    ",ans[read()]);
     48     return 0;
     49 }
     50 void Dfss(int k,int father)
     51 {
     52     for (int i=first[k]; i; i=nx[i])
     53     {
     54         int ver=vv[i];
     55         if (ver==father or ver==hea[k]) continue;
     56         Dfss(ver,k);
     57         for (int j=0; j<vec[ver].size(); ++j)
     58             t[vec[ver][j].second]=0;
     59     }
     60     if (hea[k])
     61     {
     62         Dfss(hea[k],k);
     63         root[k]=root[hea[k]];
     64     }
     65     for (int i=first[k]; i; i=nx[i])
     66     {
     67         int ver=vv[i];
     68         if (ver==father or ver==hea[k]) continue;
     69         Merge(k,ver);
     70     }
     71     for (int i=0; i<vec[k].size(); ++i)
     72     {
     73         int time=vec[k][i].first,color=vec[k][i].second;
     74         if (!t[color]) Insert(root[k],1,m,time,1,0),t[color]=time;
     75         else if (t[color]>time)
     76         {
     77             Insert(root[k],1,m,time,1,0);
     78             Insert(root[k],1,m,t[color],-1,0);
     79             t[color]=time;
     80         }
     81         Insert(root[k],1,m,time,0,1);
     82     }
     83     ans[k]=Ask(root[k],1,m,w[k]);
     84     if (hea[k])
     85     {
     86         Merge(hea[k],k);
     87         swap(vec[k],vec[hea[k]]);
     88     }
     89 }
     90 int Ask(int k,int l,int r,int weight)
     91 {
     92     if (weight<=0) return 0;
     93     if (l==r) return tr[k].num;
     94     int mid=l+r>>1,res=0;
     95     if (tr[tr[k].lc].sum<=weight)
     96     {
     97         res+=tr[tr[k].lc].num;
     98         res+=Ask(tr[k].rc,mid+1,r,weight-tr[tr[k].lc].sum);
     99         return res;
    100     }
    101     else res=Ask(tr[k].lc,l,mid,weight);
    102     return res;
    103 }
    104 void Insert(int &k,int l,int r,int goal,int col,int que)
    105 {
    106     if (!k) k=++cnt;
    107     if (l==r) 
    108     {
    109         tr[k].sum+=que; tr[k].num+=col;
    110         return ;
    111     }
    112     int mid=l+r>>1;
    113     if (goal<=mid) Insert(tr[k].lc,l,mid,goal,col,que);
    114     else Insert(tr[k].rc,mid+1,r,goal,col,que);
    115     tr[k].num=tr[tr[k].lc].num+tr[tr[k].rc].num;
    116     tr[k].sum=tr[tr[k].lc].sum+tr[tr[k].rc].sum;
    117 }
    118 void Merge(int x,int y)
    119 {
    120     for (int i=0; i<vec[y].size(); ++i)
    121         vec[x].push_back(vec[y][i]);
    122     vec[y].clear();
    123 }
    124 void Dfs(int k,int father)
    125 {
    126     for (int i=first[k]; i; i=nx[i])
    127     {
    128         if (vv[i]==father) continue;
    129         Dfs(vv[i],k);
    130         if (sze[vv[i]]>sze[hea[k]]) hea[k]=vv[i];
    131         sze[k]+=sze[vv[i]];
    132     }
    133     ++sze[k];
    134 }
    135 inline void Add(int u,int v)
    136 {
    137     vv[++tt]=v; nx[tt]=first[u]; first[u]=tt;
    138 }
    139 inline int read()
    140 {
    141     int nn=0; int ch=getchar();
    142     while (ch<'0' or ch>'9') ch=getchar();
    143     while (ch>='0' and ch<='9') nn=(nn<<3)+(nn<<1)+(ch^48),ch=getchar();
    144     return nn;
    145 }
    模板(ac)

     

    T3 大佬(kat)

      妈呀概率期望大水题。

      我这么想做概率期望,但是一碰到概率期望还是懵。

      其实很简单的。

      先解释一下为什么我们可以直接乘$n-k+1$次。

      我们每一次将方格移动一位,会发现其中有$k-1$位是重复的,那么这重复的部分怎么处理呢?其实不用处理,每次的移动会考虑到所有情况,情况的交集一定存在。

      那么找规律吧,这个……口胡好像不太好讲,就是每一位上不重不漏的算出所有情况,总情况是$m^k$。

      公式

              $ans=(n-k+1) imes sum limits _{i=1}^m sum limits _{j=1}^k {(i-1)}^{j-1} i^{k-j} w_i   inv_{m^k}$

      小弟不才。

      

     1 #include<cstdio>
     2 #define int long long
     3 #define HZOI using namespace std
     4 HZOI;
     5 const int mod=1e9+7;
     6 int n,m,k,invtot,ans;
     7 inline int Pow(int ,int );
     8 signed main()
     9 {
    10     scanf("%lld%lld%lld",&n,&m,&k);
    11     if (k>n) {puts("0"); return 0;}
    12     invtot=Pow(Pow(m,k),mod-2);
    13     for (int i=1,w; i<=m; ++i)
    14     {
    15         scanf("%lld",&w);
    16         for (int j=1; j<=k; ++j)
    17             ans=(ans+Pow(i-1,j-1)%mod*Pow(i,k-j)%mod*w%mod*invtot%mod+mod)%mod;
    18     }
    19     ans=(ans%mod*(n-k+1)+mod)%mod;
    20     printf("%lld
    ",(ans+mod)%mod); 
    21     return 0;
    22 }
    23 inline int Pow(int x,int y)
    24 {
    25     int res=1;
    26     while (y)
    27     {
    28         if (y&1) res=res%mod*x%mod;
    29         x=x%mod*x%mod;
    30         y>>=1;
    31     }
    32     return res;
    33 }
    大佬(kat)

      

  • 相关阅读:
    destoon(DT)系统中公司主页模板风格添加方法
    outlook 收Gmail邮箱邮件
    使用新网全球邮改如何对域名进行解析
    无法访问.您可能没有权限使用网络资源.局域网无法访问共享,局域网无法访问打印机的一些方法
    Microsoft Word 对象ASP教程,ASP应用
    面向对象和面向过程的区别
    图文讲解 上网本 无光驱 系统蓝屏/系统无法开机 用U盘 winpe 启动U盘 重装系统的方法(通用PE工具箱/老毛桃/大白菜WinPE)
    2.0 版本的版权底部破解
    pureftpd FTP登岸呈现530验证失败 lnmp
    word域高级应用 if 域 域邮件合并的值的更改 日期的更改
  • 原文地址:https://www.cnblogs.com/LH-Xuanluo/p/11273802.html
Copyright © 2011-2022 走看看