训练日志9 (7.31)

T1 辣鸡(ljh)

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

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

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

  这时候问题就被简化了。

  方格内部的贡献,我们可以转化成一个神奇的公式:$ res_i=(lenx-1) \times (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\n",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\n",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\n",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\n",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\n",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) \times \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\n",(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)

  

猜你喜欢

转载自www.cnblogs.com/LH-Xuanluo/p/11273802.html