C. Obtain The String
题意:给两个字符串s,t选择最少的s的子序列拼接成t
用多个s去匹配t,看能否把t匹配完,这样暴力跑每个字符会t,所以可以进行一点优化,记录s中每个字符后面出现了哪些字符,然后就可以O(1)地进行转移;
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 1e5 + 5;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
return f*res;
}
char s[maxn],t[maxn];
int nxt[maxn][30],vis[30]; //nxt[i][j]表示第i位后的j字符的位置,j是字符-'a'后的值
int main()
{
int T = read();
while(T--) {
cin>>s>>t;
int lens = strlen(s),lent = strlen(t),flag = 0;
memset(vis,0,sizeof(vis));
for(int i = 0;i < lent; ++i) vis[t[i] - 'a'] = 1;
for(int i = 0;i < lens; ++i) vis[s[i] - 'a'] = 0;
for(int i = 0;i < 26; ++i) if(vis[i]) { printf("-1\n"); flag = 1; break;}
if(flag) continue;
for(int i = 0;i < 26; ++i) nxt[lens][i] = -1;
for(int i = lens - 1;i >= 0; --i) {
for(int j = 0;j < 26; ++j) nxt[i][j] = nxt[i + 1][j];
nxt[i][s[i] - 'a'] = i;
}
int ans = 1,now = 0;
for(int i = 0;i < lent; ++i) {
now = nxt[now][t[i] - 'a'];
if(now == -1) { //now后面没有能够和t匹配的,所以重新开始匹配;
now = 0;i--;ans++;
}else ++now;
}
cout<<ans<<endl;
}
return 0;
}
题意:求解gcd(a,m) = gcd(a+x,m)这样的x有多少个( 0≤x<m);
假设gcd(a,m) = p;那么问题就转化为 gcd(a+x,m) = p ->gcd((a + x) / p,m / p) = 1;令l = a / p , r = m / p -> gcd((l + x / p),r) = 1,就是求解[l,l + r)中和r互质的数的个数,拆分成[l,r]和(r,l + r) 两个区间;
∵: gcd(a,b) = gcd(a + bt,b) (其中t为任意整数)令k是区间[1,l)中的任意一个数, gcd(k,r) = gcd(k + r,r) ,k + r ∈ (r,l + r),这表明[1,l - 1]中和r互质的数和(r,l + r)中和r互质的数是相等的;
∵ 我们的答案 = [l,r]满足要求的数 + (r,l + r) 满足要求的数
求[l,r] 等价于 求[1,r]满足要求的数 - [1,l - 1]中满足要求的数,
而[1,l - 1]中满足要求的数 = (r,l + r)中满足要求的数
所以得出结论 我们的答案 = [1,r]满足要求的数,求r的欧拉函数就是了
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 1e5 + 5;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
return f*res;
}
ll a,m;
ll gcd(ll a,ll b) {
return (b == 0 ? a : gcd(b,a%b));
}
ll Euler(ll x) {
ll res = x;
for(ll i = 2;i <= sqrt(x); ++i) {
if(x % i == 0) {
res -= res / i;
while(x % i == 0) x/=i;
}
}
if(x > 1) res -= res / x;
return res;
}
int main()
{
int T = read();
while(T--) {
cin>>a>>m;
ll p = gcd(a,m);
ll x = m / p;
cout<<Euler(x)<<endl;
}
return 0;
}