$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

Codeforces 1182

1182 C

题意

\(n\) 个英文单词。
两个单词半相似当且仅当这两个单词的元音数量相等。
两个单词相似当且仅当这两个单词半相似且两个单词的最后一个元音相同。
y不是元音。保证每个单词至少含有一个元音。
一个歌词含有四个单词 \(a,b,c,d\) ,且 \(a\)\(b\) 半相似, \(c\)\(d\) 相似。
问这 \(n\) 个单词每个只选一次,最多能组成多少个歌词。并输出一种解决方案。

Examples

input

14
wow
this
is
the
first
mcdics
codeforces
round
hooray
i
am
proud
about
that

output

3
about proud
hooray round
wow first
this is
i that
mcdics am
input
7
arsijo
suggested
the
idea
for
this
problem

output

0

input

4
same
same
same
differ

output

1
same differ
same same

歌词有两种情况:

  • 两对相似;
  • 一对相似,一对半相似。

那么先凑满第二种再凑第一种。
如何知道哪几对单词是相似的?请自行思考。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=100003;
int n,cnt[maxn],p[maxn],ANS[maxn>>2][4],CNT;
string S[maxn];
char s[1000003],last[maxn];
vector<int> v[2],u;
char isvowel(char c){return c=='a'?1:(c=='e'?2:(c=='i'?3:(c=='o'?4:(c=='u'?5:0))));}
bool cmp(int x,int y){return cnt[x]==cnt[y]?last[x]<last[y]:cnt[x]<cnt[y];}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%s",s);
		S[i]=s;
		for(int j=0;s[j];j++){
			if(isvowel(s[j]))cnt[i]++,last[i]=isvowel(s[j]);
		}
		p[i]=i;
	}
	sort(p+1,p+n+1,cmp);
	for(int _i=1;_i<=n;){
		int i=p[_i],nxt=p[_i+1];
		if(_i<=n&&cnt[i]==cnt[nxt]&&last[i]==last[nxt]){
			v[0].push_back(i);
			v[1].push_back(nxt);
			_i+=2;
		}
		else{
			u.push_back(i);
			_i++;
		}
	}
	sort(u.begin(),u.end(),cmp);
	int i,j;
	for(i=0,j=0;i<v[0].size()&&j+1<u.size();){
		if(cnt[u[j]]==cnt[u[j+1]]){
			CNT++;
			ANS[CNT][1]=v[0][i],ANS[CNT][3]=v[1][i],ANS[CNT][0]=u[j],ANS[CNT][2]=u[j+1];
			i++,j+=2;
		}
		else{
			j++;
		}
	}
	for(;i+1<v[0].size();i+=2){
		CNT++;
		ANS[CNT][1]=v[0][i],ANS[CNT][3]=v[1][i],ANS[CNT][2]=v[0][i+1],ANS[CNT][0]=v[1][i+1];
	}
	printf("%d\n",CNT);
	for(i=1;i<=CNT;i++){
		for(j=0;j<=3;j++){
			printf("%s%c",S[ANS[i][j]].c_str(),j&1?'\n':' ');
		}
	}
	return 0;
}

1182 D

\[\color{white}{\text{???}} \]

1182 E

题意

\(f_x=c^{2x-6}*f_{x-1}*f_{x-2}*f_{x-3}\)
给你 \(n,f_1,f_2,f_3,c\) ,求 \(f_n\% 10^9+7\)\((n\le 10^{18})\)

Examples

input
5 1 2 5 3
output
72900
input
17 97 41 37 11
output
317451037

首先证明:对于质数 \(p\)\(a^{p-1}≡1(\% p)\)
费马小定理。
然后我们把 \(f_n\) 用含 \(f_1,f_2,f_3,c\) 的式子表示出来,发现这四个项的指数是一个与 \(n\) 有关的递推式,所以矩阵快速幂加速即可。加速时模数要取 \(10^9+6\)

Code

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int Plus(int x,int y,int p=mod){return (x+=y)>=p?x%p:x;}
int mul(long long x,int y,int p=mod){return x*y%p;}
int qpow(int x,int y,int p=mod){
	int ans=1;
	while(y){
		if(y&1)ans=mul(ans,x,p);
		x=mul(x,x,p);
		y>>=1;
	}
	return ans;
}
struct matrix{
	static const int maxn=6;
	int a[maxn][maxn],n,m;
	matrix(){}
	matrix(int _n,int _m,bool flag=0):n(_n),m(_m){
		memset(a,0,sizeof(a));
		if(flag)for(int i=1;i<=n;i++)a[i][i]=1;
	}
	friend matrix operator *(const matrix &A,const matrix &B){
		matrix RET(A.n,B.m);
		for(int i=1;i<=A.n;i++)for(int j=1;j<=B.m;j++)for(int k=1;k<=A.m;k++)
			RET.a[i][j]=Plus(RET.a[i][j],mul(A.a[i][k],B.a[k][j],mod-1),mod-1);
		return RET;
	}
	friend matrix operator ^(matrix A,long long B){
		matrix RET(A.n,A.n,1);
		while(B){
			if(B&1)RET=RET*A;
			A=A*A;
			B>>=1;
		}
		return RET;
	}
};
int main(){
	long long n;
	int f1,f2,f3,c,nc,n1,n2,n3;
	scanf("%lld%d%d%d%d",&n,&f1,&f2,&f3,&c);
	matrix T(5,5),A(5,1);
	T.a[1][2]=T.a[2][3]=T.a[3][1]=T.a[3][2]=T.a[3][3]=T.a[3][4]=T.a[3][5]=T.a[4][4]=T.a[4][5]=T.a[5][5]=1;
	A.a[5][1]=2;
	A=(T^(n-3))*A;
	nc=A.a[3][1];
	T=matrix(3,3),A=matrix(3,1);
	T.a[1][2]=T.a[2][3]=T.a[3][1]=T.a[3][2]=T.a[3][3]=1;
	A.a[1][1]=1;
	A=(T^(n-3))*A;
	n1=A.a[3][1];
	A=matrix(3,1);
	A.a[2][1]=1;
	A=(T^(n-3))*A;
	n2=A.a[3][1];
	A=matrix(3,1);
	A.a[3][1]=1;
	A=(T^(n-3))*A;
	n3=A.a[3][1];
	printf("%d\n",mul(mul(mul(qpow(c,nc),qpow(f1,n1)),qpow(f2,n2)),qpow(f3,n3)));
	return 0;
}
posted @ 2019-06-19 11:22  chc_1234567890  阅读(303)  评论(0编辑  收藏  举报