题目链接
有三个数组 A A A=( A 1 A_1 A1, A 2 A_2 A2,…), B B B=( B 1 B_1 B1, B 2 B_2 B2,…), C C C=( C 1 C_1 C1, C 2 C_2 C2,…),问有多少对 A i A_i Ai= B C j B_{C_j} BCj?(有点逆过来做的思想)
我的做法是用cnt数组记录A数组中出现的每个数的个数,cnt[a[i]]++,最后对C数组遍历,因为C数组中的数是B数组中的索引,ans+=cnt[b[c[i]]].
#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
int a[N],b[N],c[N],cnt[N];
ll ans;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],cnt[a[i]]++;
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=1;i<=n;i++)ans+=cnt[b[c[i]]];
cout<<ans<<endl;
return 0;
}
题目链接
在长度为A+B的字符串有A次a出现,B次b出现,找出按字典序排列第K个的字符串。(组合数+思维)
第一个样例的解释如下:2个a出现,2个b出现,按字典序排序如下:aabb,abab,abba,baab,baba,bbaa.第4个即baab.
从第1位开始枚举每一位,显然要构成一个a个a和b个b组成的字符串,第1位是a的有 C a + b − 1 a − 1 C_{a+b-1}^{a-1} Ca+b−1a−1个数,判断当前的k和它的关系(用now存),
if(k > now) k -= now, putchar('b'), --b;
else putchar('a'), --a;
第2位是a的话是有 C a + b − 2 a − 1 C_{a+b-2}^{a-1} Ca+b−2a−1…(n=a+b)即
for(int i=1; i<=n; i++) {
ll now = C[n-i][a - 1];//注意a=0时的情况
代码如下:
#include
using namespace std;
typedef long long ll;
const int N=110;
ll C[N][N];
void get_C(int n) {
C[0][0] = 1;
for(int i = 1; i <= n; i++) {
C[i][0] = 1;
for(int j = 1; j <= i; j++)
C[i][j]= C[i - 1][j] + C[i - 1][j - 1];
}
}
int main(){
int a,b;
ll k;//这里注意开long long 煞笔了
cin>>a>>b>>k;
get_C(60);
// for(int i=0;i<=n;i++){
// for(int j=0;j<=n;j++) {
// cout<
// }
// cout<
// }
// cout<
int n=a+b;
for(int i=1; i<=n; i++) {
ll now = C[n-i][a - 1];//注意a=0时的情况
if(a==0)now=0;
// cout<<"now:"<
if(k > now) k -= now, putchar('b'), --b;
else putchar('a'), --a;
}
return 0;
}