zoukankan      html  css  js  c++  java
  • 【SDOI2018】反回文串(【ARC064 F】Rotated Palindromes 加强版)

    题意

      给你一个正整数 (n),求有多少字符集为 (1)(k) 之间整数的字符串,使得该字符串可以由一个长度为 (n) 的回文串循环移位得到。
      ARC原题 (100\%) 的数据是 (n,kle 10^9)
      SDOI改编后,(30\%) 的数据是 (n,kle 10^{10})(60\%) 的数据是 (n,kle 10^{14})(100\%) 的数据是 (n,kle 10^{18})……

    题解

    (n,kle 10^{10})

      考虑一个回文串,设它的循环节长度为 (x),若 (x) 为奇数,则对答案贡献 (x);若为偶数,则对答案贡献 (frac{x}{2})
      我们按 (x) 把所有字符串分类,统计每一类的数量。
      设 (f(i)) 表示最小循环节长度为 (i) 的回文串数量,(F(i)) 表示循环节长度为 (i)(即 (i) 是最小循环节长度的正整数倍)能得到新回文串的回文串数量。
      则 $$F(i)=sumlimits_{d|i} f(d)$$ $$ans = sumlimits_{d|n} f(d) imes egin{cases} d(d为奇数) frac{d}{2}(d为偶数) end{cases}$$
      显然有 (F(i)=k^{lceil frac{i}{2} ceil}),我们可以解 (f(d)) 了。
      (nle 10^{10}) 时,因数最多约有 (6700) 多个。所以我们要求出 (6700) 多个 (f(d))

      移项得 (f(i)=F(i)-sumlimits_{d|i 且 d≠i} f(d))
      递推 (f) 即可。

      复杂度大约 (O(6700^2))

    #include<bits/stdc++.h>
    #define ll long long
    #define N 7000
    #define mod 1000000007
    using namespace std;
    inline int read(){
    	int x=0; bool f=1; char c=getchar();
    	for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
    	for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
    	if(f) return x;
    	return 0-x;
    }
    int n,k,d[N],f[N],cnt,ans;
    int Pow(int x, int y){
    	int ret=1;
    	while(y){
    		if(y&1) ret=(ll)ret*x%mod;
    		x=(ll)x*x%mod;
    		y>>=1;
    	}
    	return ret;
    }
    int main(){
    	n=read(), k=read();
    	int nn=sqrt(n);
    	for(int i=1; i<=nn; ++i)
    		if(n%i==0){
    			d[++cnt]=i, f[cnt]=Pow(k,(i+1)/2);
    			for(int j=1; j<cnt; ++j)
    				if(i%d[j]==0) f[cnt]=((f[cnt]-f[j])%mod+mod)%mod;
    			ans=(ans+(ll)f[cnt]*((i&1)?i:i/2)%mod)%mod;
    		}
    	for(int i=nn; i>=1; --i)
    		if(n%i==0){
    			int ii=n/i;
    			d[++cnt]=ii, f[cnt]=Pow(k,(ii+1)/2);
    			for(int j=1; j<cnt; ++j)
    				if(ii%d[j]==0) f[cnt]=((f[cnt]-f[j])%mod+mod)%mod;
    			ans=(ans+(ll)f[cnt]*((ii&1)?ii:ii/2)%mod)%mod;
    		}
    	cout<<ans<<endl;
    	return 0;
    }
    

    (n,kle 10^{14})

      (F(i)=sumlimits_{d|i} f(d)) 不是莫比乌斯反演式子?
      根据公式转化成 (f(i)=sumlimits_{d|i} F(d)mu(frac{i}{d}))
      我们最多只需要求约 (17280)(mu),因此可以暴力 ( ext{dfs}) 计算每个 (mu(i)),然后就求出 (f(i)) 了。
      发现 ( ext{dfs}) 的时候,(n) 的每个质因数只需要乘 (0)(1) 个,乘 (2) 个的话 (mu) 值就变成了 (0) 了。
      于是复杂度变为 (O(17280 imes 2^{12})),但约数数量通常不多,更不会卡满上界 (17280),所以卡卡常就能 (60) 分?

    (n,kle 10^{18})

      看不懂,请移步 scb 的博客。

  • 相关阅读:
    纠结我一上午的asp.net操作mysql问题
    C#术语【转自MSDN】
    asp.net新手必知必会——我们为什么要用asp.net
    图片在浏览器中底部对齐———解决方法之一
    asp.net做的网站比asp做的站慢?
    我是一个可悲的程序员
    今天离开职场去过自己的潇洒人生
    asp.net应用程序重新启动
    asp.net分页解决方法
    80. 删除有序数组中的重复项 II
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/11519710.html
Copyright © 2011-2022 走看看