第十周 11.1-11.7

11.1-11.3

什么都没干。

11.4

HNU 10104 病毒

又是卡了很久的题目。其实已经改出了可以AC的代码。但是不能理解差别。

后来试了一种可以理解的简单做法发现能过就先这样吧- -。

题意:给n个二进制串,问能否构造出不包含这n个串的无限长二进制串。

最后的做法是简单的丢到AC自动机里。然后dfs找一个没有单词结尾的环。

没有单词结尾是这个节点和它顺着fail到root的路上都没有单词结尾。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 using namespace std;
  7 const int maxnode=3e4+10,sigma_size=2;
  8 const int maxn=3e4+10;
  9 int n,p[maxn];
 10 char s[maxnode];
 11 
 12 struct Ac_auto
 13 {
 14     int Next[maxnode][sigma_size];
 15     int fail[maxnode];
 16     int val[maxnode];
 17     int vis[maxnode];
 18     int sz;
 19     Ac_auto(){sz=1;memset(Next[0],0,sizeof(Next[0]));}
 20     void init()
 21     {
 22         vis[0]=val[0]=0;
 23         sz=1;memset(Next[0],0,sizeof(Next[0]));
 24     }
 25     int idx(char c) {return c-'0';}
 26 
 27     void insert(char *s)
 28     {
 29         int u=0,n=strlen(s);
 30         for(int i=0;i<n;i++)
 31         {
 32             int c=idx(s[i]);
 33             if(!Next[u][c])
 34             {
 35                 memset(Next[sz],0,sizeof(Next[sz]));
 36                 val[sz]=vis[sz]=0;
 37                 Next[u][c]=sz++;
 38             }
 39             u=Next[u][c];
 40         }
 41         val[u]=1;
 42     }
 43 
 44     void build()
 45     {
 46         queue<int> q;
 47         fail[0]=0;
 48         for(int i=0;i<sigma_size;i++) if(Next[0][i])
 49         {
 50             fail[Next[0][i]]=0;
 51             q.push(Next[0][i]);
 52         }
 53         while(!q.empty())
 54         {
 55             int pos=q.front(); q.pop();
 56             for(int i=0;i<sigma_size;i++)
 57             {
 58                 if(!Next[pos][i]) Next[pos][i]=Next[fail[pos]][i];
 59                 else
 60                 {
 61                     fail[Next[pos][i]]=Next[fail[pos]][i];
 62                     q.push(Next[pos][i]);
 63                 }
 64             }
 65         }
 66     }
 67 
 68     bool dfs(int pos)
 69     {
 70         vis[pos]=1;
 71         for(int i=0;i<sigma_size;i++)
 72         {
 73             int u=Next[pos][i],flag=0;
 74             while(u)
 75             {
 76                 if(val[u]) {flag=1; break;}
 77                 u=fail[u];
 78             }
 79             if(flag) continue;
 80             if(vis[Next[pos][i]]||dfs(Next[pos][i])) return true;
 81         }
 82         vis[pos]=0;
 83         return false;
 84     }
 85 
 86 }ACA;
 87 
 88 int main(void)
 89 {
 90     while(~scanf("%d",&n))
 91     {
 92         ACA.init();
 93         for(int i=1;i<=n;i++)
 94         {
 95             scanf("%s",s+p[i-1]);
 96             ACA.insert(s+p[i-1]);
 97             p[i]=p[i-1]+strlen(s+p[i-1]);
 98         }
 99         ACA.build();
100         puts(ACA.dfs(0)?"TAK":"NIE");
101     }
102     return 0;
103 }
Aguin

11.5

补BC。

HDU 5524 Subtrees

我的做法是把子树分成满二叉树和非满二叉树两种统计。

深度记为dep。如果本身就是满。那么满二叉子树有dep种。

如果自身不是满。那么左右子树必有一颗满。

左满有dep-2种。右满有dep-1种。

再统计非满的二叉子树个数。

只要找到最小的非满二叉子树。那么所有包含这棵树的都是。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 LL pow[61];
 6 
 7 int main(void)
 8 {
 9     pow[0]=1LL;
10     for(int i=1;i<61;i++) pow[i]=pow[i-1]*2LL;
11     LL N;
12     while(~scanf("%I64d",&N))
13     {
14         int ans,dep=1,cnt=0;
15         while(N>pow[dep]-1LL) dep++;
16         LL t=N-pow[dep-1]+1;
17         if(t==pow[dep-1]) ans=2*dep-1;
18         else if(t<pow[dep-2]) ans=2*dep-3;
19         else ans=2*dep-2;
20         while(t%2LL==0) ans--,t/=2LL;
21         printf("%d
",ans);
22     }
23     return 0;
24 }
Aguin

HDU 5525 Product

司老大题解

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const LL MOD=1e9+7;
 8 const int maxn=1e5;
 9 LL pr[maxn],cnt[maxn];
10 int pos[maxn];
11 
12 void GetPrime()
13 {
14     memset(pr,0,sizeof(pr));
15     for(int i=2;i<=maxn;i++)
16     {
17         if(!pr[i]) pr[++pr[0]]=i;
18         for(int j=1;j<=pr[0]&&pr[j]*i<=maxn;j++)
19         {
20             pr[i*pr[j]]=1;
21             if(i%pr[j]==0) break;
22         }
23     }
24     for(int i=1;i<=pr[0];i++) pos[pr[i]]=i;
25     return;
26 }
27 
28 LL qpow(LL a,LL b)
29 {
30     LL d=1,t=a;
31     while(b)
32     {
33         if(b%2) d=(d*t)%MOD;
34         b/=2;
35         t=(t*t)%MOD;
36     }
37     return d;
38 }
39 
40 int main(void)
41 {
42     GetPrime();
43     int n;
44     while(~scanf("%d",&n))
45     {
46         memset(cnt,0,sizeof(cnt));
47         for(int i=1;i<=n;i++)
48         {
49             LL x; scanf("%I64d",&x);
50             int cur=i;
51             for(int j=1;j<=pr[0];j++)
52             {
53                 if(cur<(LL)pr[j]*pr[j]) break;
54                 if(cur%pr[j]==0)
55                 {
56                     LL t=0;
57                     while(cur%pr[j]==0) {t++; cur/=pr[j];}
58                     cnt[j]=(cnt[j]+x*t)%(2*MOD-2);
59                 }
60             }
61             if(cur>1) cnt[pos[cur]]=(cnt[pos[cur]]+x)%(2*MOD-2);
62         }
63         LL Q=1LL,ans=1LL;
64         for(int i=1;i<=pr[0];i++) Q=Q*(cnt[i]+1)%(2*MOD-2);
65         for(int i=1;i<=pr[0];i++)
66         {
67             LL b=(cnt[i]*Q)%(2*MOD-2)/2;
68             ans=ans*qpow(pr[i],b)%MOD;
69         }
70         printf("%I64d
",ans);
71     }
72     return 0;
73 }
Aguin

HDU 5526 Lie

按照官方题解敲的。(好像并没有多少人去补这题。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 int num[1010][1010];
 7 int val[1010][1010];
 8 int dp[1010];
 9 
10 int main(void)
11 {
12     int N;
13     while(~scanf("%d",&N))
14     {
15         memset(num,0,sizeof(num));
16         memset(val,0,sizeof(val));
17         memset(dp,0,sizeof(dp));
18         for(int i=1;i<=N;i++)
19         {
20             int A,B;
21             scanf("%d%d",&A,&B);
22             if(A+B+1>N) continue;
23             num[A+B+1][0]++;
24             num[A+B+1][A+1]++;
25         }
26         for(int i=1;i<=N;i++)
27         {
28             for(int j=1;i*j<=N;j++)
29             {
30                 int tmp=0;
31                 for(int k=1;k<=i*j;k++) tmp+=min(j,num[i][k]);
32                 val[i][j]=tmp;
33             }
34             for(int v=N;v>=0;v--)
35                 for(int j=1;i*j<=N;j++)
36                     if(v>=i*j) dp[v]=max(dp[v],dp[v-i*j]+val[i][j]);
37         }
38         printf("%d
",dp[N]);
39     }
40     return 0;
41 }
Aguin

补完一套BC。

11.6-11.7

什么都没干。

原文地址:https://www.cnblogs.com/Aguin/p/4937040.html