码迷,mamicode.com
首页 > 其他好文 > 详细

【做题】训练53

时间:2017-10-09 20:51:24      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:work   main   字符串   最短路   bit   tmp   直接   mes   void   

A

可以推一发公式。设f(x)表示n=x时的方案数。当新加入一个元素时,有如下两种情况:

1、与新加入的元素相邻的两个元素颜色不同,方案数就是f(x-1)*(m-2)。

2、与新加入的元素相邻的两个元素颜色相同,方案数就是f(x-2)*(m-1)。

(也就是直接插入两个元素,一个颜色有(m-1)种,另一个为满足该条件就只有一种颜色可行)

因此,得到f(x)=(m-2)*f(x-1)+(m-1)*f(x-2)。

再用矩阵快速幂优化就行了。(还要加特判)

时间复杂度O(logn*2^3)。

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int MOD=998244353;
 5 //f(n)=f(n-1)*(m-2)+f(n-2)*(m-1)
 6 struct Martix{
 7     int mar[3][3];
 8     Martix operator * (const Martix& x)const{
 9         Martix res;
10         memset(res.mar,0,sizeof(res.mar));
11         for(int i=1;i<=2;i++)
12          for(int j=1;j<=2;j++)
13           for(int k=1;k<=2;k++)
14           {
15             (res.mar[i][j]+=mar[i][k]*x.mar[k][j])%=MOD;
16           }
17         return res;
18     }
19 }base,st,tmp;
20 Martix power(Martix a,int b)
21 {
22     if(b==0) return base;
23     Martix t=power(a,b>>1);
24     t=t*t;
25     if(b&1) t=t*a;
26     return t;
27 }
28 signed main()
29 {
30     int n,m;
31     scanf("%lld%lld",&n,&m);
32     if(m==1&&n!=1) return 0*printf("%lld\n",0ll);
33     tmp.mar[1][1]=m*(m-1)%MOD*(m-2)%MOD;
34     tmp.mar[1][2]=tmp.mar[2][1]=m*(m-1)%MOD;
35     tmp.mar[2][2]=m;
36     if(n==1) return 0*printf("%lld\n",m);
37     if(n==2) return 0*printf("%lld\n",m*(m-1)%MOD);
38     if(n==3) return 0*printf("%lld\n",m*(m-1)%MOD*(m-2)%MOD);
39     for(int i=1;i<=2;i++) base.mar[i][i]=1;
40     st.mar[1][1]=m-2;st.mar[2][1]=(m-1);st.mar[1][2]=1;
41     printf("%lld\n",(tmp*power(st,n-3)).mar[1][1]);
42     return 0;
43 }

 

B

首先,01矩阵显然可以转化为01串。(就当这是对第一题的温馨暗示吧)

然后,我就不会了。

以下是某大佬的解法:

对于任意一对01串,其中有若干位是不同的,那么选取这些位中的任意一个就使这对字符串得到区分。

于是这几位对这对01串的区分是有贡献的,就在他们的贡献中加入这一对字符串。(具体用状态压缩实现)

于是我们得到每一位的贡献。

对于每一对01串,我们都是需要区分的,因此假设我们选择了若干位来区分这些01串,那么这几位的贡献值按位或的结果必须是 (1<<C(k,2))-1,即每一位都是1。

于是这就成了选取最少的数使它们按位或的结果为给定的数。因为数据极小,直接dp就行了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=110,PO=(1<<15)+10,K=10;
 4 int dp[N][PO],n,m,k,l,tot;
 5 int a[K][N],b[N];
 6 void init()
 7 {
 8     memset(b,0,sizeof(b));
 9     char tmp;
10     scanf("%d%d%d",&n,&m,&k);
11     l=n*m;
12     for(int i=1;i<=k;i++)
13     {
14         for(int j=1;j<=l;j++)
15         {
16             tmp=getchar();
17             while(tmp!=1&&tmp!=0) tmp=getchar();
18             a[i][j]=tmp-0;
19         }
20     }
21     int num=1;
22     for(int i=1;i<=k;i++)
23      for(int j=i+1;j<=k;j++)
24      {
25          for(int pos=1;pos<=l;pos++)
26           if(a[i][pos]!=a[j][pos])
27            b[pos]|=1<<num>>1;
28          num++;
29      }
30     num--;
31     tot=1<<num;
32 }
33 int main()
34 {
35     int t;
36     scanf("%d",&t);
37     while(t--)
38     {
39         init();
40         memset(dp,0x3f,sizeof(dp));
41         dp[0][0]=0;
42         for(int i=1;i<=l;i++)
43          for(int j=0;j<tot;j++)
44          {
45              if(dp[i][j|b[i]]>dp[i-1][j]+1)
46               dp[i][j|b[i]]=dp[i-1][j]+1;
47              if(dp[i][j]>dp[i-1][j])
48               dp[i][j]=dp[i-1][j];
49          }
50         printf("%d\n",dp[l][tot-1]);
51     }
52     return 0;
53 }

 

C

关键路径,两遍最短路的事。对于关键路径上的每一条边(u,v),把从dis[u]到dis[u]之间的点的答案加一就可以了。

然而我实现写萎了。实际上一个个点差分,再按距离顺序一个个点求和就可以了。

  1 #include<bits/stdc++.h>
  2 #define Pii pair<int,int>
  3 #define INF 1<<30
  4 using namespace std;
  5 const int N=2010,M=200010;
  6 struct edge{
  7     int la,b,v;
  8 }con[M<<1];
  9 int fir[N],tot;
 10 void add(int from,int to,int val)
 11 {
 12     con[++tot].la=fir[from];
 13     con[tot].b=to;
 14     con[tot].v=val;
 15     fir[from]=tot;
 16 }
 17 int n,s,t,m;
 18 vector<int>fa[N];
 19 bool vis[N];
 20 int inq[N],diss[N],dist[N];
 21 struct cmp{
 22     bool operator () (const Pii &x,const Pii &y)
 23     {
 24         return x.second>y.second;
 25     }
 26 };
 27 priority_queue<Pii,vector<Pii>,cmp>q;
 28 void dijkstra(int st,int *dis)
 29 {
 30     while(!q.empty()) q.pop();
 31     for(int i=1;i<=n;i++) dis[i]=INF;
 32     dis[st]=0;
 33     q.push(make_pair(st,dis[st]));
 34     inq[st]=1;
 35     int pos;
 36     while(!q.empty())
 37     {
 38         pos=q.top().first;
 39         q.pop();
 40         if(--inq[pos]>0) continue;
 41         for(int i=fir[pos];i;i=con[i].la)
 42         {
 43             if(dis[con[i].b]>dis[pos]+con[i].v)
 44             {
 45                 dis[con[i].b]=dis[pos]+con[i].v;
 46                 q.push(make_pair(con[i].b,dis[con[i].b]));
 47                 inq[con[i].b]++;
 48             }
 49         }
 50     }
 51 }
 52 struct value{
 53     int pos,val,num;
 54     bool operator < (const value& x)const{
 55         if(pos!=x.pos) return pos<x.pos;
 56         else return val<x.val;
 57     }
 58 }avail[N*3];
 59 int cnt,ans[N];
 60 void work()
 61 {
 62     int ru,chu,tmp=0;
 63     for(int i=1;i<=n;i++) if(diss[i]+dist[i]==diss[t]) vis[i]=1;
 64     for(int i=1;i<=n;i++) if(vis[i])
 65     {
 66         ru=chu=-1;
 67         for(int j=fir[i];j;j=con[j].la) if(vis[con[j].b])
 68         {
 69             if(diss[con[j].b]+con[j].v==diss[i]) ru++;
 70             if(diss[i]+con[j].v==diss[con[j].b]) chu++;
 71         }
 72         avail[++cnt]=(value){diss[i],ru*(-1),0};
 73         avail[++cnt]=(value){diss[i],0,i};
 74         avail[++cnt]=(value){diss[i],chu*1,0};
 75     }
 76     sort(avail+1,avail+cnt+1);
 77     for(int i=1;i<=cnt;i++)
 78     {
 79         if(avail[i].val==0) ans[avail[i].num]=tmp;
 80         else tmp+=avail[i].val;
 81     }
 82     ans[s]=1;ans[t]=1;
 83 }
 84 int main()
 85 {
 86     int from,to,val;
 87     scanf("%d%d%d%d",&n,&s,&t,&m);
 88     for(int i=1;i<=m;i++)
 89     {
 90         scanf("%d%d%d",&from,&to,&val);
 91         add(from,to,val);
 92         add(to,from,val);
 93     }
 94     dijkstra(s,diss);
 95     dijkstra(t,dist);
 96     work();
 97     for(int i=1;i<=n;i++) printf("%d ",ans[i]);
 98     printf("\n");
 99     return 0;
100 }

 

小结:今天题目确实偏简单。要积极给每道题写解法,以及在实现想法时不要不经考虑乱写。

【做题】训练53

标签:work   main   字符串   最短路   bit   tmp   直接   mes   void   

原文地址:http://www.cnblogs.com/cly-none/p/7642210.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!