• 9.6——模拟赛


    T1 洛谷 P3014 [USACO11FEB]牛线Cow Line

    题目背景

    征求翻译。如果你能提供翻译或者题意简述,请直接发讨论,感谢你的贡献。

    题目描述

    The N (1 <= N <= 20) cows conveniently numbered 1...N are playing yet another one of their crazy games with Farmer John. The cows will arrange themselves in a line and ask Farmer John what their line number is. In return, Farmer John can give them a line number and the cows must rearrange themselves into that line.

    A line number is assigned by numbering all the permutations of the line in lexicographic order.

    Consider this example:

    Farmer John has 5 cows and gives them the line number of 3.

    The permutations of the line in ascending lexicographic order: 1st: 1 2 3 4 5

    2nd: 1 2 3 5 4

    3rd: 1 2 4 3 5

    Therefore, the cows will line themselves in the cow line 1 2 4 3 5.

    The cows, in return, line themselves in the configuration '1 2 5 3 4' and ask Farmer John what their line number is.

    Continuing with the list:

    4th : 1 2 4 5 3

    5th : 1 2 5 3 4

    Farmer John can see the answer here is 5

    Farmer John and the cows would like your help to play their game. They have K (1 <= K <= 10,000) queries that they need help with. Query i has two parts: C_i will be the command, which is either 'P' or 'Q'.

    If C_i is 'P', then the second part of the query will be one integer A_i (1 <= A_i <= N!), which is a line number. This is Farmer John challenging the cows to line up in the correct cow line.

    If C_i is 'Q', then the second part of the query will be N distinct integers B_ij (1 <= B_ij <= N). This will denote a cow line. These are the cows challenging Farmer John to find their line number.

    输入输出格式

    输入格式:

    • Line 1: Two space-separated integers: N and K

    • Lines 2..2*K+1: Line 2*i and 2*i+1 will contain a single query.

    Line 2*i will contain just one character: 'Q' if the cows are lining up and asking Farmer John for their line number or 'P' if Farmer John gives the cows a line number.

    If the line 2*i is 'Q', then line 2*i+1 will contain N space-separated integers B_ij which represent the cow line. If the line 2*i is 'P', then line 2*i+1 will contain a single integer A_i which is the line number to solve for.

    输出格式:

    • Lines 1..K: Line i will contain the answer to query i.

    If line 2*i of the input was 'Q', then this line will contain a single integer, which is the line number of the cow line in line 2*i+1.

    If line 2*i of the input was 'P', then this line will contain N space separated integers giving the cow line of the number in line 2*i+1.

    输入输出样例

    输入样例#1:
    5 2 
    P 
    3 
    Q 
    1 2 5 3 4 
    
    输出样例#1:
    1 2 4 3 5 
    5 


    康托展开:
      1 #include <algorithm>
      2 #include <string>
      3 #include <cstdio>
      4 #include <map>
      5 
      6 using namespace std;
      7 
      8 #define LL long long
      9 LL jc[21]={1,1,2,6,24,120,720,5040,40320,362880,328800,
     10             39916800,479001600,6227020800LL,87178291200LL,
     11             1307674368000LL,20922789888000LL,355687428096000LL,
     12             6402373705728000LL,121645100408832000LL,2432902008176640000LL};
     13 map<LL,string>m1;
     14 map<string,LL>m2;
     15 LL n,m,x,cnt,tmp[26];
     16 char num[26],sta[26];
     17 string a;
     18 
     19 inline void read(LL &x)
     20 {
     21     x=0; register char ch=getchar();
     22     for(;ch>'9'||ch<'0';) ch=getchar();
     23     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
     24 }
     25 
     26 void work1()
     27 {
     28     for(int i=1; i<=n; ++i) num[i-1]=i+'0';
     29     for(;1;next_permutation(num,num+n))
     30     {
     31         if(m2[num]) break;
     32         m1[++cnt]=num;
     33         m2[num]=cnt;
     34     }
     35     for(char s[2];m--;)
     36     {
     37         scanf("%s",s);
     38         if(s[0]=='P')
     39         {
     40             read(x); a=m1[x];
     41             for(int i=0;i<n-1;i++)
     42                 printf("%d ",a[i]-'0');
     43             printf("%d
    ",a[n-1]-'0');
     44         }
     45         else
     46         {
     47             for(int i=0; i<n; ++i)
     48                 read(x),a[i]=x+'0';
     49             printf("%lld
    ",m2[a]);
     50         }
     51     }
     52 }
     53 
     54 int AC()
     55 {
     56 //    freopen("permutation.in","r",stdin);
     57 //    freopen("permutation.out","w",stdout);
     58 
     59     read(n),read(m);
     60     /*jc[0]=1;
     61     for(LL i=1; i<=n; ++i) jc[i]=jc[i-1]*i;*/
     62     if(n<=5) work1();
     63     else
     64     {
     65         for(char s[2];m--;)
     66         {
     67             scanf("%s",s);
     68             if(s[0]=='P')
     69             {
     70                 read(x); x--;
     71                 bool use[26]={0};
     72                 for(LL j,i=1; i<=n; ++i)
     73                 {
     74                     LL tmp=x/jc[n-i];
     75                     for(j=1; j<=n; ++j)
     76                     if(!use[j])
     77                     {
     78                         if(!tmp) break;
     79                         tmp--;
     80                     }
     81                     use[j]=1;
     82                     x%=jc[n-i];
     83                     printf("%d ",j);
     84                 }
     85                 puts("");
     86             }
     87             else
     88             {
     89                 for(LL i=1; i<=n; ++i) read(tmp[i]);
     90                 LL ans=0;
     91                 for(LL t=0,i=1;i<=n;i++)
     92                 {
     93                     t=0;
     94                     for(LL j=i+1; j<=n; ++j)
     95                         if(tmp[i]>tmp[j]) t++;
     96                     ans+=t*jc[n-i];
     97                 }
     98                 printf("%I64d
    ",ans+1);
     99             }
    100         }
    101     }
    102     return 0;
    103 }
    104 
    105 int Hope=AC();
    106 int main(){;}
    考试60分
    阶乘没打表就能过了、、

     1 #include <cstdio>
     2 
     3 using namespace std;
     4 
     5 #define LL long long
     6 LL jc[21];
     7 LL n,m,x,cnt,tmp[26];
     8 
     9 inline void read(LL &x)
    10 {
    11     x=0; register char ch=getchar();
    12     for(;ch>'9'||ch<'0';) ch=getchar();
    13     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    14 }
    15 
    16 int AC()
    17 {
    18 //    freopen("permutation.in","r",stdin);
    19 //    freopen("permutation.out","w",stdout);
    20 
    21     read(n),read(m);
    22     jc[0]=1; for(LL i=1; i<=n; ++i) jc[i]=jc[i-1]*i;
    23     for(char s[2];m--;)
    24     {
    25         scanf("%s",s);
    26         if(s[0]=='P')
    27         {
    28             read(x); x--;
    29             bool use[26]={0};
    30             for(LL j,i=0; i<n; ++i)
    31             {
    32                 LL tmp=x/jc[n-i-1];
    33                 for(j=1; j<=n; ++j)
    34                 if(!use[j])
    35                 {
    36                     if(!tmp) break;
    37                     tmp--;
    38                 }
    39                 use[j]=1;
    40                 x%=jc[n-i-1];
    41                 printf("%d ",j);
    42             }
    43             puts("");
    44         }
    45         else
    46         {
    47             for(LL i=0; i<n; ++i) read(tmp[i]);
    48             LL ans=0;
    49             for(LL t=0,i=0;i<n;i++)
    50             {
    51                 t=0;
    52                 for(LL j=i+1; j<n; ++j)
    53                     if(tmp[i]>tmp[j]) t++;
    54                 ans+=t*jc[n-i-1];
    55             }
    56             printf("%lld
    ",ans+1);
    57         }
    58     }
    59     return 0;
    60 }
    61 
    62 int Hope=AC();
    63 int main(){;}
    AC


    T2 洛谷 U3357 C2-走楼梯

    题目背景

    在你成功地解决了上一个问题之后,方方方不禁有些气恼,于是他在楼梯上跳来跳去,想要你求出他跳的方案数。..

    题目描述

    方方方站在一个n阶楼梯下面,他每次可以往上跳一步或两步,往下跳一步到四步(由于地心引力跳得比较远),而且在往下跳的时候你只能踩在你往上跳时踩过的格子。

    现在方方方在楼梯上乱跳,想问他跳到楼梯顶上最后又跳回楼梯下面的方案数mod 2333333。

    请注意:针对题目有歧义的情况,这里再说明一下。方方方只能一直向上跳,跳到楼梯最上面,然后再往下跳,跳回楼梯最底下。

    输入输出格式

    输入格式:

    输入一行一个数n。

    输出格式:

    输出方方方跳回楼梯下面的方案数mod 2333333。

    输入输出样例

    输入样例#1:
    5
    输出样例#1:
    52
    输入样例#2:
    7654321
    输出样例#2:
    451197
    输入样例#3:
    3
    输出样例#3:
    8

    说明

    对于30%的数据,n<=10。

    对于100%的数据,1<=n<=10^7。

    (其实也可以做到10^18,可是出题人懒)

     1 #include <cstdio>
     2 
     3 const int mod(2333333);
     4 const int N(1e7+5);
     5 int n;
     6 
     7 inline void read(int &x)
     8 {
     9     x=0; register char ch=getchar();
    10     for(;ch>'9'||ch<'0';) ch=getchar();
    11     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    12 }
    13 
    14 int ans;
    15 bool vis[N],vis_[N];
    16 void DFS_(int now)
    17 {
    18     if(now==0)
    19     {
    20         ans++;
    21         ans%=mod;
    22         return ;
    23     }
    24     for(int i=1; i<=4; ++i)
    25     {
    26         if(vis_[now-i]||(now-i<0)) continue;
    27         if(!vis[now-i]) continue;
    28         vis_[now-i]=1;
    29         DFS_(now-i);
    30         vis_[now-i]=0;
    31     }
    32 }
    33 void DFS(int now)
    34 {
    35     if(now==n)
    36     {
    37         DFS_(now);
    38         return ;
    39     }
    40     for(int i=1; i<=2; ++i)
    41     {
    42         if(vis[now+i]||(now+i>n)) continue;
    43         vis[now+i]=1;
    44         DFS(now+i);
    45         vis[now+i]=0;
    46     }
    47 }
    48 
    49 int AC()
    50 {
    51 //    freopen("stair.in","r",stdin);
    52 //    freopen("stair.out","w",stdout);
    53     
    54     read(n); vis[0]=1; DFS(0);
    55     printf("%d
    ",ans);
    56     return 0;
    57 }
    58 
    59 int Hope=AC();
    60 int main(){;}
    考试,爆搜30分

    正解DP:

    向下走可以看成向上走

    f[i]表示第一次向上走到i,第二次向上也走到i的方案数

    如果第二次向上走1步到i,这1步第一次有1种走法

    如果第二次向上走2步到i,这2步第一次有2种走法

    如果第二次向上走3步到i,这3步第一次有3种走法

    如果第二次向上走4步到i,这4步第一次有5种走法

    所以状态转移方程:f[i]=f[i-1]+f[i-2]*2+f[i-3]*3+f[i-4]*5

     1 #include <cstdio>
     2 
     3 const int mod(2333333);
     4 const int N(1e7+5);
     5 int n,f[N];
     6 
     7 inline void read(int &x)
     8 {
     9     x=0; register char ch=getchar();
    10     for(;ch>'9'||ch<'0';) ch=getchar();
    11     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    12 }
    13 
    14 int AC()
    15 {
    16     read(n);
    17     f[0]=1; f[1]=1; f[2]=3; f[3]=8;
    18     for(int i=4;i<=n;i++)
    19         f[i]=(f[i-1]+f[i-2]*2+f[i-3]*3+f[i-4]*5)%mod;
    20     printf("%d
    ",f[n]);
    21     return 0;
    22 }
    23 
    24 int Hope=AC();
    25 int main(){;}
    AC

    T3 BZOJ——1821: [JSOI2010]Group 部落划分 Group

    Description

    聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗。只是,这一切都成为谜团了——聪聪根本就不知道部落究竟是如何分布的。 不过好消息是,聪聪得到了一份荒岛的地图。地图上标注了N个野人居住的地点(可以看作是平面上的坐标)。我们知道,同一个部落的野人总是生活在附近。我们把两个部落的距离,定义为部落中距离最近的那两个居住点的距离。聪聪还获得了一个有意义的信息——这些野人总共被分为了K个部落!这真是个好消息。聪聪希望从这些信息里挖掘出所有部落的详细信息。他正在尝试这样一种算法: 对于任意一种部落划分的方法,都能够求出两个部落之间的距离,聪聪希望求出一种部落划分的方法,使靠得最近的两个部落尽可能远离。 例如,下面的左图表示了一个好的划分,而右图则不是。请你编程帮助聪聪解决这个难题。 

    Input

    第一行包含两个整数N和K(1< = N < = 1000,1< K < = N),分别代表了野人居住点的数量和部落的数量。
    接下来N行,每行包含两个正整数x,y,描述了一个居住点的坐标(0 < =x, y < =10000)

    Output

    输出一行,为最优划分时,最近的两个部落的距离,精确到小数点后两位。

    Sample Input

    4 2
    0 0
    0 1
    1 1
    1 0


    Sample Output

    1.00

    HINT

     

    Source

    JSOI2010第二轮Contest1

    最小生成树+乱搞活似一个大zz

     1 #include <algorithm>
     2 #include <cstdio>
     3 #include <cmath>
     4 
     5 const int N(1026);
     6 int n,k,sumedge;
     7 struct Node {
     8     int x,y;
     9 }peo[N];
    10 struct Edge {
    11     double dis;
    12     int u,v;
    13     bool operator < (const Edge x)const
    14     {
    15         return dis>x.dis;
    16     }
    17     Edge(int u=0,int v=0,double dis=0.0):u(u),v(v),dis(dis){}
    18 }e[N*N];
    19 
    20 inline void read(int &x)
    21 {
    22     x=0; register char ch=getchar();
    23     for(;ch>'9'||ch<'0';) ch=getchar();
    24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    25 }
    26 
    27 double Get_dis(int u,int v)
    28 {
    29     return sqrt((double)(peo[u].x-peo[v].x)*(peo[u].x-peo[v].x)+(double)(peo[u].y-peo[v].y)*(peo[u].y-peo[v].y));
    30 }
    31 
    32 int fa[N];
    33 int find(int x)
    34 {
    35     return fa[x]==x?x:fa[x]=find(fa[x]);
    36 }
    37 
    38 #define max(a,b) (a>b?a:b)
    39 #define min(a,b) (a<b?a:b)
    40 
    41 int AC()
    42 {
    43     freopen("people.in","r",stdin);
    44     freopen("people.out","w",stdout);
    45     
    46     read(n),read(k);
    47     for(int i=1; i<=n; ++i)
    48         read(peo[i].x),read(peo[i].y);
    49     for(int i=1; i<=n; ++i)
    50         for(int j=1; j<=n; ++j)
    51         if(i!=j) e[++sumedge]=Edge(i,j,Get_dis(i,j));
    52     int cnt=0;
    53     double ans=0;
    54     std::sort(e+1,e+sumedge+1);
    55     for(int i=1; i<=n; ++i) fa[i]=i;
    56     for(int fx,fy,i=1; i<=sumedge; ++i)
    57     {
    58         fx=find(e[i].u), fy=find(e[i].v);
    59         if(fa[fx]==fy) continue;
    60         fa[fx]=fy;
    61         if(++cnt<=k) ans=max(ans,e[i].dis);
    62         else ans=min(ans,e[i].dis);
    63         if(cnt==n-1) break;
    64     }
    65     printf("%.2lf",ans);
    66     return 0;
    67 }
    68 
    69 int Hope=AC();
    70 int main(){;}
    考试的zz写法。。10分

    最小生成树:

    首先按照边权排序,要让最小的距离最大,那么就让那些很小的距离放在部落内部;

    原来有n个部落,而每加入一条边就会减少一个,ans=最小生成树的第n-k+1条边。

     1 #include <algorithm>
     2 #include <cstdio>
     3 #include <cmath>
     4 
     5 const int N(1026);
     6 int n,k,sumedge;
     7 double dist[N];
     8 struct Node {
     9     int x,y;
    10 }peo[N];
    11 struct Edge {
    12     double dis;
    13     int u,v;
    14     bool operator < (const Edge &x)const
    15     {
    16         return dis<x.dis;
    17     }
    18     Edge(int u=0,int v=0,double dis=0.0):u(u),v(v),dis(dis){}
    19 }e[N*N];
    20 
    21 inline void read(int &x)
    22 {
    23     x=0; register char ch=getchar();
    24     for(;ch>'9'||ch<'0';) ch=getchar();
    25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    26 }
    27 
    28 double Get_dis(int u,int v)
    29 {
    30     return sqrt((double)(peo[u].x-peo[v].x)*(peo[u].x-peo[v].x)+(double)(peo[u].y-peo[v].y)*(peo[u].y-peo[v].y));
    31 }
    32 
    33 int fa[N];
    34 int find(int x)
    35 {
    36     return fa[x]==x?x:fa[x]=find(fa[x]);
    37 }
    38 
    39 #define max(a,b) (a>b?a:b)
    40 #define min(a,b) (a<b?a:b)
    41 
    42 int AC()
    43 {
    44 //    freopen("people.in","r",stdin);
    45 //    freopen("people.out","w",stdout);
    46     
    47     read(n),read(k);
    48     for(int i=1; i<=n; ++i)
    49         read(peo[i].x),read(peo[i].y);
    50     for(int i=1; i<=n; ++i)
    51         for(int j=1; j<=n; ++j)
    52         if(i!=j) e[++sumedge]=Edge(i,j,Get_dis(i,j));
    53     int cnt=0;
    54     double ans=0;
    55     std::sort(e+1,e+sumedge+1);
    56     for(int i=1; i<=n; ++i) fa[i]=i;
    57     for(int fx,fy,i=1; i<=sumedge; ++i)
    58     {
    59         fx=find(e[i].u), fy=find(e[i].v);
    60         if(fa[fx]==fy) continue;
    61         fa[fx]=fy;
    62         if(++cnt>n-k)
    63         {
    64             printf("%.2lf",e[i].dis);
    65             return 0;
    66         }
    67     }
    68     return 0;
    69 }
    70 
    71 int Hope=AC();
    72 int main(){;}
    AC
    ——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
  • 相关阅读:
    bzoj 3209: 花神的数论题 数位dp
    bzoj 1799: [Ahoi2009]self 同类分布 数位dp
    Codeforces 755 F. PolandBall and Gifts 多重背包+贪心
    Educational Codeforces Round 17 D. Maximum path DP
    Codeforces Round #396 (Div. 2) C. Mahmoud and a Message DP
    Codeforces 768 E. Game of Stones 博弈DP
    HDU 2457/POJ 3691 DNA repair AC自动机+DP
    Codefoces 791D. Bear and Tree Jumps 树形DP
    Codeforces 440 D. Berland Federalization 树形DP,记录DP
    Codeforces 709E. Centroids 树形DP
  • 原文地址:https://www.cnblogs.com/Shy-key/p/7484966.html
Copyright © 2020-2023  润新知