J题
Just Shuffle
题意:已知置换 e = {1,2,…,n } 变换k次后得到一个置换a(已知),求置换e变换一次得到的置换x。
题解:这题我们能想到,对于变换规则,会存在一些环,意味着变换环的大小后置换不变。我们针对每个环考虑,设环的大小为len,变换一次的状态等价于变换 len * y + 1 次,那我们从已知考虑,已知变换k次后的状态,那么我们就能推出变换 2 * k ,3 * k,4 * k , … , 次后的状态( 我们将变换k次当成一单位次的变换 )。那我们猜想如果 x * k = len * y + 1, 方程两边同时 % len , 方程变成 x * k % len = 1;解这个方程,可以枚举答案,利用逆元的定义,答案在 0 - len -1 之间。
#include
#define ll long long
using namespace std;
const int maxn = 1e5+10;
int a[maxn];
int vis[maxn],ans[maxn],to[maxn];
vector<int> G;
void dfs(int p)
{
vis[p] = 1;
G.push_back(a[p]);
if(!vis[to[p]])
{
dfs(to[p]);
}
}
void go(int k)
{
int len = G.size() ,inv;
for(int i=0;i<len;i++) if((ll)i*k%len==1) { inv = i; break; }
for(int i=0;i<len;i++)
ans[G[i]] = G[(i+inv)%len];
}
int main()
{
int n,k; scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),to[i] = a[i];
for(int i=1;i<=n;i++)
{
G.clear();
if(!vis[i])
{
dfs(i);
go(k);
}
}
for(int i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n");
}
A题
All with Pairs
题解:将每个字符串的后缀hash值保存起来,用双hash值来减冲突,然后枚举每个前缀,在hash_map中找后缀,但是需要去重,对于两个aaa来说,我枚举a ,aa ,aaa时,另一个aaa都计算了贡献,而只能计算aaa的贡献,因为要最长。我们发现如果我们计算了aaa的贡献,那么必然也要计算a 和 aa的贡献,这样就重复了,所以这其实就是一个字符串next数组,我们只需要减去next数组的贡献就行了。
#include
#define ll long long
using namespace std;
const int maxn = 1e6+10;
ll base[2] = {43,47};
ll mod[2] = {1000000007,998244353} , h[3][maxn];
ll f[2][maxn];
void init()
{
f[0][0] = f[1][0] = 1;
for(int i=1;i<maxn;i++)
for(int j=0;j<2;j++) f[j][i] = f[j][i-1] * base[j] % mod[j];
}
ll gets(int l,int r,int id)
{
return (h[id][r] - h[id][l-1] * f[id][r-l+1] % mod[id] + mod[id]) % mod[id];
}
const ll mood=1e9+7;
const int maxsz=3e6+7;
template<typename key,typename val>
class hash_map{public:
struct node{key u;val v;int next;};
vector<node> e;
int head[maxsz],nume,numk,id[maxsz];
int geths(pair<ll,ll> &u){
int x=(1ll*u.first*mood+u.second)%maxsz;
if(x<0) return x+maxsz;
return x;
}
val& operator[](key u){
int hs=geths(u);
for(int i=head[hs];i;i=e[i].next)if(e[i].u==u) return e[i].v;
if(!head[hs])id[++numk]=hs;
if(++nume>=e.size())e.resize(nume<<1);
return e[nume]=(node){u,0,head[hs]},head[hs]=nume,e[nume].v;
}
void clear(){
for(int i=0;i<=numk;i++) head[id[i]]=0;
numk=nume=0;
}
};
hash_map<pair<ll,ll>,ll> mp;
string s[maxn];
int nt[maxn];
void getnext(string ss)
{
int k = -1 , j = 0;
int n = ss.size();
nt[0] = -1;
while(j<n)
{
if(k==-1||ss[j]==ss[k])
{
j++; k++;
nt[j] = k;
}
else k = nt[k];
}
}
ll cnt[maxn];
const ll modd =998244353;
int main()
{
std::ios::sync_with_stdio(false);
init();
int n ;
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++)
{
int len = s[i].size();
for(int j=0;j<len;j++)
{
int tmp = s[i][j] - 'a' + 1;
for(int k=0;k<2;k++)
h[k][j+1] = ( h[k][j] * base[k] % mod[k] + tmp ) % mod[k];
}
pair<ll,ll> tmp;
for(int j=1;j<=len;j++)
{
tmp.first = gets(j,len,0);
tmp.second = gets(j,len,1);
mp[tmp]++;
}
}
for(int i=1;i<=n;i++)
{
int len = s[i].size();
for(int j=0;j<len;j++)
{
int tmp = s[i][j] - 'a' + 1;
for(int k=0;k<2;k++)
h[k][j+1] = ( h[k][j] * base[k] % mod[k] + tmp ) % mod[k];
}
getnext(s[i]);
pair<ll,ll> tmp;
for(int j=len;j>=1;j--)
{
tmp.first = gets(1,j,0);
tmp.second = gets(1,j,1);
int xx = mp[tmp];
cnt[j] += xx;
cnt[j] %= modd;
cnt[nt[j]] = ( cnt[nt[j]] - xx + modd ) % modd;
}
}
ll ans = 0;
// for(int i=1;i<=10;i++) cout<
for(int i=1;i<maxn;i++)
{
ans = ( ans + ( cnt[i] * ( (ll)i*i % modd ) ) % modd ) % modd;
}
cout<<ans<<endl;
}