题意 
给定一个长度为 n n n   的字符串 s s s   代表 A A A   的工作模式:第 i i i   个字符为 # 代表 A A A   在第 i i i   天工作,为 . 代表 A A A   在第 i i i   天不工作。现构造一个长度为 m m m   的字符串 t ′ t' t ′  (m m m   是 n n n   的因子且 m ≠ n m\neq n m  = n  ) ,将其拷贝 n m \dfrac{n}{m} m n    份得到字符串 t t t  ,代表 B B B   的工作模式。 要求在这 n n n   天中,每一天都至少有一人工作。求不同的字符串 t t t   的数量。
题解 
记 f ( n ) f(n) f ( n )  为长度为 n n n   的字符串 t ′ t' t ′   能生成的不同字符串 t t t   的数量。注意到,长度是 n n n   的因子的字符串 t ′ ′ t'' t ′′   生成的字符串可能和 t ′ t' t ′   生成的相同,例如:t ′ t' t ′   为 ## 而 t ′ ′ t'' t ′′   为 #。所以,我们再定义 g ( n ) g(n) g ( n )   为长度为 n n n   的字符串 t ′ t' t ′   能生成的,且不能由更短的字符串生成的不同字符串 t t t   的数量。
最终我们要求的式子为
∑ i ∣ n , i ≠ n g ( i ) \sum_{i\mid n,i\neq n}g(i)
 i ∣ n , i  = n ∑  g ( i ) 
直接求 g g g   不太好求,但是 f f f   容易求得。所以考虑 f f f   和 g g g   的关系
f ( n ) = ∑ d ∣ n g ( d ) f(n)=\sum_{d|n}g(d)
 f ( n ) = d ∣ n ∑  g ( d ) 
这是莫比乌斯反演的经典形式,很容易得到
g ( n ) = ∑ d ∣ n μ ( d ) f ( n d ) g(n)=\sum_{d|n}\mu(d)f(\frac{n}{d})
 g ( n ) = d ∣ n ∑  μ ( d ) f ( d n  ) 
接下来就是推式子
∑ i ∣ n , i ≠ n g ( i ) = ∑ i ∣ n , i ≠ n ∑ d ∣ n μ ( d ) f ( n d ) = ∑ d ∣ n , d ≠ n f ( d ) ∑ k ∣ n , k ≠ n d μ ( d ) = ∑ d ∣ n , d ≠ n f ( d ) ( ϵ ( n d ) − μ ( n d ) ) = ∑ d ∣ n , d ≠ n − μ ( n d ) f ( d ) \begin{aligned}
\sum_{i\mid n,i\neq n}g(i)
&=\sum_{i\mid n,i\neq n}\sum_{d\mid n}\mu(d)f(\frac{n}{d})\\
&=\sum_{d\mid n,d\neq n}f(d)\sum_{k\mid n,k\neq \frac{n}{d}}\mu(d)\\
&=\sum_{d\mid n,d\neq n}f(d)(\epsilon(\frac{n}{d})-\mu(\frac{n}{d}))\\
&=\sum_{d\mid n,d\neq n}-\mu(\frac{n}{d})f(d)
\end{aligned}
 i ∣ n , i  = n ∑  g ( i )  = i ∣ n , i  = n ∑  d ∣ n ∑  μ ( d ) f ( d n  ) = d ∣ n , d  = n ∑  f ( d ) k ∣ n , k  = d n  ∑  μ ( d ) = d ∣ n , d  = n ∑  f ( d ) ( ϵ ( d n  ) − μ ( d n  )) = d ∣ n , d  = n ∑  − μ ( d n  ) f ( d )  
然后这个题目就做完了qwq。
代码 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include  <bits/stdc++.h>  using  namespace  std;typedef  long  long  ll;const  int  maxn=1e5 ;const  int  p=998244353 ;int  n,cnt,f[maxn+5 ],vis[maxn+5 ],pri[maxn+5 ],mu[maxn+5 ],tag[maxn+5 ]; ll P2[maxn+5 ]; string s;void  init ()  {     mu[1 ]=1 ;     for (int  i=2 ;i<=maxn;i++)     {         if (!vis[i]) pri[++cnt]=i,mu[i]=-1 ;         for (int  j=1 ;j<=cnt&&i*pri[j]<=maxn;j++)         {             vis[i*pri[j]]=1 ;             if (i%pri[j]==0 )             {                 mu[i*pri[j]]=0 ;                 break ;             }             mu[i*pri[j]]=-mu[i];         }     }     P2[0 ]=1 ;     for (int  i=1 ;i<=maxn;i++) P2[i]=P2[i-1 ]*2 %p; }void  solve (int  m)  {     for (int  i=1 ;i<=m;i++) tag[i]=0 ;     for (int  i=0 ;i<n;i++)          if (s[i]=='.' ) tag[i%m+1 ]=1 ;     int  cnt=0 ;     for (int  i=1 ;i<=m;i++)         if (!tag[i]) cnt++;     f[m]=P2[cnt];  }int  main ()  {     ios::sync_with_stdio (false );     cin.tie (nullptr );     init ();     cin>>n>>s;     ll ans=0 ;     for (int  i=1 ;i<n;i++)     {         if (n%i) continue ;         solve (i);         ans=(ans-mu[n/i]*f[i]%p+p)%p;     }     cout<<ans<<'\n' ;     return  0 ; }
 
题意 
给定一张有向图,含有一些边 ( s i , t i ) (s_i,t_i) ( s i  , t i  )  。同时,给出一些限制 ( l i , r i ) (l_i,r_i) ( l i  , r i  )  。要求构造一个排列 p p p  ,满足以下条件:
p s i < p t i p_{s_i}<p_{t_i} p s i   < p t i    
l i ≤ p i ≤ r i l_i\leq p_i\leq r_i l i  ≤ p i  ≤ r i   
 
题解 
很显然这张图一定是DAG,否则无法满足条件1。
由于存在拓扑关系,每个限制 ( l i , r i ) (l_i,r_i) ( l i  , r i  )   事实上也会限制每个点的前驱。具体地,对于边 ( s , t ) (s,t) ( s , t )  ,有 p s ≤ r s p_s\leq r_s p s  ≤ r s    且 p s ≤ p t − 1 ≤ r t p_s\leq p_t-1\leq r_t p s  ≤ p t  − 1 ≤ r t   。即 p s ≤ min  ( r s , r t − 1 ) p_s\leq \min(r_s,r_t-1) p s  ≤ min ( r s  , r t  − 1 )  。所以,在反图上跑一遍拓扑序,更新一下每个点的上界,保证对每条边 ( s , t ) (s,t) ( s , t )  ,有 r s < r t r_s<r_t r s  < r t   。
接下来考虑构造这个排列,从 1 1 1   到 n n n   依次将每个数分配,在分配 i i i   时,候选点 v v v   需要满足两个条件:
l v ≤ i l_v\leq i l v  ≤ i  
v v v   的所有前驱都已被分配了数 
 
在所有候选点中,选择 r r r   最小的,将 i i i   分配给它。
最后还需要再检查一遍是否满足题目给出的两个限制。
(正确性的证明可以参考官方题解)
代码 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include  <bits/stdc++.h>  using  namespace  std;const  int  maxn=2e5 +5 ;int  p[maxn],in[maxn],in1[maxn]; vector<int > a[maxn]; vector<int > g[maxn],g1[maxn];struct  node  {     int  id,l,r;     bool  operator  < (const  node x) const  {return  r>x.r;} }nodes[maxn];int  main ()  {     ios::sync_with_stdio (false );     cin.tie (nullptr );     int  n,m;cin>>n>>m;     for (int  i=1 ;i<=m;i++)     {         int  u,v;cin>>u>>v;         g[u].push_back (v),g1[v].push_back (u);         in[v]++,in1[u]++;     }     for (int  i=1 ;i<=n;i++)     {         int  l,r;cin>>l>>r;         nodes[i]={i,l,r};         a[l].push_back (i);     }     queue<int > q;     for (int  i=1 ;i<=n;i++)         if (!in1[i]) q.push (i);     int  cnt=0 ;     while (!q.empty ())     {         int  u=q.front ();q.pop ();         cnt++;         for (auto  v:g1[u])         {             nodes[v].r=min (nodes[v].r,nodes[u].r-1 );             in1[v]--;             if (!in1[v]) q.push (v);         }     }     if (cnt!=n) cout<<"No" <<'\n' ;     else      {         priority_queue<node> pq;         for (int  i=1 ;i<=n;i++)         {             for (auto  j:a[i])                  if (!in[j]) pq.push (nodes[j]);             if (pq.empty ()) break ;             int  u=pq.top ().id;pq.pop ();             p[u]=i;             for (auto  v:g[u])             {                 in[v]--;                 if (!in[v]&&nodes[v].l<=i) pq.push (nodes[v]);             }         }         bool  ok=1 ;         for (int  i=1 ;i<=n;i++)         {             if (p[i]<nodes[i].l||p[i]>nodes[i].r) ok=0 ;             for (auto  j:g[i])                 if (p[j]<p[i]) ok=0 ;         }         if (!ok) cout<<"No" <<'\n' ;         else          {             cout<<"Yes" <<'\n' ;             for (int  i=1 ;i<=n;i++) cout<<p[i]<<" \n" [i==n];         }     }     return  0 ; }