BestCoder Round #41------>

现在才补上,主要是第三题看到神奇代码:

A:只能说真的好题,我写的很复杂,开始的时候没发现其实可以改变相对顺序,结果。。。

思路(请忽视代码吧!写的太乱,另外模拟题一直是我最大的不足

有5个,如果我们全排列所有的话,生成5!=120中,

对一种判断的方法是固定一个数,我们可以生成合法序列的一种,然后跟原来数列对比。

这里还要考虑10 11 12 13 1这种排列方式。找到最优解。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<string.h>
 5 #include<string>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<vector>
10 
11 #define N 123456
12 #define inf 0x3f3f3f
13 using namespace std;
14 typedef long long ll;
15 
16 
17 string ss[5];
18 
19 int a[6];
20 int b[6];
21 
22 
23 int main()
24 {
25     int T;
26     scanf("%d",&T);
27 
28     while (T--)
29     {
30         for (int i=0;i<5;i++) cin>>ss[i];
31         int sxbk=123;
32         sort(ss,ss+5);
33 
34         do
35         {
36         for (int i=0;i<5;i++)
37         {
38         if    (ss[i][0]=='A')   a[i]=100;
39         else  if (ss[i][0]=='B') a[i]=200;
40         else  if (ss[i][0]=='C') a[i]=300;
41         else  if (ss[i][0]=='D') a[i]=400;
42         int m=ss[i].size();
43 
44         if (m==2) a[i]+=ss[i][1]-'0';
45         else a[i]+=(ss[i][1]-'0')*10+ss[i][2]-'0';
46         }
47 
48         for (int i=0;i<5;i++)
49         {
50             b[i]=a[i]%100;
51             int wei=a[i]/100;
52             for (int j=i-1;j>=0;j--)
53             {
54                 b[j]=b[i]-1;
55                 if (b[j]==0) b[j]=1;
56             }
57 
58             for (int j=i+1;j<5;j++)
59             {
60                 b[j]=b[j-1]+1;
61                 if (b[j]==14) b[j]=1;
62             }
63 
64             int flag=0;
65             for (int j=0;j<5;j++)
66             {
67                 if (b[j]==13&&j<3) flag=1;
68                 if (b[j]==1&&!(j==0||j==4) ) flag=1;
69             }
70 
71 
72             if (flag) continue;
73 
74             int tmp=0;
75             for (int j=0;j<5;j++) {
76              b[j]+=wei*100;
77              if (a[j]!=b[j]) tmp++;
78             }
79             sxbk=min(sxbk,tmp);
80            }
81         } while (next_permutation(ss,ss+5));
82         printf("%d
",sxbk);
83     }
84     return  0;
85 }
View Code

B,写下A题没多少时间了,忘记考虑字串相等也是输的情况。

所以就是简单的判断奇数偶数,然后用map 判断有多少个完全相等的字串

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<string.h>
 5 #include<string>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<vector>
10 
11 #define N 123456
12 #define inf 0x3f3f3f
13 using namespace std;
14 typedef long long ll;
15 
16 int  a[23456];
17 
18 map<string,int>mp;
19 string ss;
20 
21 int gcd(int aa,int bb)
22 {
23     if (aa==0) return 1;
24     if (bb==0) return aa;
25     return gcd(bb,aa%bb);
26 }
27 
28 
29 int main()
30 {
31     int T;
32     scanf("%d",&T);
33     while (T--)
34     {
35     int n;
36     scanf("%d",&n);
37     mp.clear();
38 
39     int jishu,ou;
40     jishu=ou=0;
41 
42     for (int i=1;i<=n;i++)
43     {
44            cin>>ss;
45            a[i]=ss.size();
46            if (a[i]&1) jishu ++;
47            else    ou++;
48            mp[ss]++;
49      }
50 
51      int  xx=n*(n-1)/2;
52 
53      int    yy=jishu*ou;
54 
55      map<string,int>::iterator it;
56      for ( it=mp.begin();it!=mp.end();it++){
57         int tmp=it->second;
58         yy+=tmp*(tmp-1)/2;
59      }
60 
61 
62      int tt=gcd(yy,xx);
63     // if (yy==0) tt=1,xx=1;
64 
65      printf("%d/%d
",yy/tt,xx/tt);
66      }
67     return  0;
68 }
View Code

C:

------------------------------------------分----------------------------------------------隔--------------------------------------线

这道题赛后补了好久,不能跟上代码的思维度了。

先丢AC代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<string>
 6 #include<vector>
 7 #include<stdio.h>
 8 
 9 using namespace std;
10 
11 typedef long long LL;
12 typedef double DB;
13 typedef pair<int, int> PII;
14 typedef vector<int> VI;
15 const int MX = 100005;
16 
17 const int MC = 450;
18 const int MOD = 998244353;
19 int f[MX], g[MX];
20 int *p = f, *q = g;
21 int s[MX];
22 
23 void init() {
24      int i, j;
25      p[0] = 1;
26 
27         for (i = 1; i < MC; i++) {
28         for (j = 0; j < MX; j++)  s[j] = (s[j] + p[j]) % MOD;
29         for (j = 0; j < i;  j++)  q[j] = 0;
30         for (j = i; j < MX; j++)  q[j] = (p[j - i] + q[j - i]) % MOD;
31         swap(p, q);
32         }
33 
34     for (j = 1; j < MX; j++) s[j] = (s[j] + s[j - 1]) % MOD;
35 }
36 
37 int main() {
38 
39     int tc, n, c, st, en, rlt;
40 
41     init();
42     for (scanf("%d", &tc); tc--; ) {
43         scanf("%d%d%d%d", &n, &c, &st, &en);
44         rlt = s[en - c];
45         cout<<s[en-c]<<" "<<s[st-c]<<endl;
46         if (st > c) rlt = (rlt + MOD - s[st - c - 1]) % MOD;
47        // printf("%d
", rlt);
48     }
49     return 0;
50 }
View Code

然后是我转换DP方程的代码:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<math.h>
 5 
 6 using namespace std;
 7 const int MC=448;
 8 const int MX=100001;
 9 const int MOD= 998244353;
10 
11 int s[MX];
12 int dp[MC][MX];//表示 用多少个数,构成和为MX 的方案数
13 
14 void init()
15 {
16    dp[0][0]=1;
17    
18    
19    
20    for (int i=1;i<MC;i++)  {
21    for (int j=0;j<MX;j++)  s[j]=(s[j]+dp[i-1][j])%MOD;//s[j]表示组成和为j的方案数,不管有多少个数。
22    for (int j=i;j<MX;j++)  dp[i][j]=(dp[i][j-i]+dp[i-1][j-i])%MOD;// 太神奇这里这个方程
23    //这个转移方程的意思是:类似01背包,dp[i-1][j-i]表示再加入i这个points,dp[i][j-i]表示不懂
24    //可能表示一种转移即dp[i][j-i]的方案同样可以构成dp[i][j].
25    //希望这里能有解释一下。
//BC题解有:
//转移的时候,要么把之前选择的每一个数增加一,要么在把之前选择的每一个数都增加一个基础上,再新加入一个当前大小为1的数。
26    }
27 
28    for (int j=1;j<MX;j++) s[j]=(s[j]+s[j-1])%MOD;//前缀和,s[i]表示构成1-i所有的方案数
29 }
30 
31 int main()
32 {
33    int T;
34    scanf("%d",&T);
35    init();
36    while (T--)
37    {
38      int n,c,l,r;
39      scanf("%d%d%d%d",&n,&c,&l,&r);
40      int ans=s[r-c];
41      
42      if (l>c) ans=(ans+MOD-s[l-c-1])%MOD;
43      printf("%d
",ans);
44    }
45    return 0;
46 }

本来第二个代码也可以O(nsqrt(n)),但是爆了空间,必须剩下空间。

思路:都是先预处理出S【I】表示生成1-i所有的方案数。

然后减减就可以了。

INIT部分;在代码中,希望能解释代码中我的疑问,

原文地址:https://www.cnblogs.com/forgot93/p/4520765.html