目录
A 、digits 2 (简单构造)
太简单就不写了。
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
scanf("%d",&T);
while(T--){
int a;
scanf("%d",&a);
for(int i=0;i<a;i++){
printf("%d",a);
}
printf("\n");
}
return 0;
}
B generator 1 (十进制快速幂)
题意:
给出然后给出一个n,n的范围是
,然后计算
分析:
因为是个矩阵,所以没办法用欧拉降幂,但是又恐于数太大,直接转化二进制快速幂肯定超时,所以先进行十进制拆分,模拟而二进制进行计算。
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef struct martix{
ll a[2][2];
martix(){
mm(a,0);
a[0][0]=a[1][1]=1;
}
}mat;
mat mul(mat a,mat b,ll mod){
mat res;
rep(i,0,1){
rep(j,0,1){
res.a[i][j]=0;
}
}
rep(i,0,1){
rep(j,0,1){
rep(k,0,1){
res.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
res.a[i][j]%=mod;
}
}
}
return res;
}
mat quick_two(mat a,ll b,ll mod){
mat res;
while(b){
if(b&1) res=mul(res,a,mod);
a=mul(a,a,mod);
b>>=1;
}
return res;
}
mat quick_ten(mat a,char b[],ll mod){
mat res;
int len=strlen(b);
for(int i=len-1;i>=0;i--){
if(b[i]!='0') res=mul(res,quick_two(a,b[i]-'0',mod),mod);
a=quick_two(a,10ll,mod);
}
return res;
}
char n[1000006];
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ll x0,x1,a,b;
ll mod;
scanf("%lld%lld%lld%lld%s%lld",&x0,&x1,&a,&b,n,&mod);
int len=strlen(n);
if(n[len-1]!='0') n[len-1]-=1;
else{
len--;
while(n[len]=='0'){
n[len]='9';
len--;
}
n[len]--;
}
mat tmp;
tmp.a[0][0]=a;tmp.a[0][1]=b,tmp.a[1][0]=1ll,tmp.a[1][1]=0;
mat res=quick_ten(tmp,n,mod);
ll ans=(x1*res.a[0][0]%mod+x0*res.a[0][1]%mod)%mod;
printf("%lld\n",ans);
return 0;
}
C、 generator 2 (BSGS)
题意:
计算满足条件的最小的i,给出v,使得等号右边同余v
分析:
将上述等式进行化简就可以看出来是BSGS了
但是可能会TLE(理论不会啊感觉)
所以分快再分的小点,就分1000一块吧,可是还有点卡,同一份代码有时候能过有时候不能过。
通过这题我发现int比longlong快,puts比printf快
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
int x0,a,b,mod;
ll n;
int t1=1001,t2=1e6;
inline ll quick_pow(ll a,int b){
ll res=1ll;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
inline ll inv(ll a){
return quick_pow(a,mod-2)%mod;
}
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
scanf("%d",&T);
while(T--){
scanf("%lld%d%d%d%d",&n,&x0,&a,&b,&mod);
int Q;
unordered_map<int,int> up;
scanf("%d",&Q);
ll p=quick_pow(a,t1);
int tmp=1;
for(int i=1;i<=t2;i++){
tmp=1ll*tmp*p%mod;
if(!up.count(tmp))
up[tmp]=t1*i;
}
int ni=inv((1ll*(a-1)*x0%mod+b+mod)%mod);
while(Q--){
ll v;
scanf("%lld",&v);
if(a==0){
if(v==x0) puts("0");
else if(v==b) puts("1");
else puts("-1");
continue;
}else if(a==1){
ll ans=1ll*(v-x0+mod)%mod*inv(b)%mod;
if(ans<n) printf("%lld\n",ans);
else puts("-1");
continue;
}else{
v=(v*(a-1)%mod+b)%mod*ni%mod;
int ans=mod+1;
int tmp3=v;
for(int i=0;i<=t1;i++){
if(up.count(tmp3)){
ans=min(ans,up[tmp3]-i);
}
tmp3=1ll*tmp3*a%mod;
}
if(1ll*ans>=n||ans==mod+1) puts("-1");
else printf("%d\n",ans);
}
}
}
return 0;
}
E、 independent set 1 (状压DP)
题意:
给出一个无向无环图,计算这个图的所有子图的最大独立子集之和。
分析:
因为n只有26,所以考虑位压缩进行计算。
该点连的边用二进制位存储起来。
固定左端点,对后面的二进制位依次枚举即可。注意要减去本身包含的边。
注意内存,所以采用char进行存储。
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
int g[26];
char dp[(1<<26)];
int n,m;
int ans=0;
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
scanf("%d%d",&n,&m);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
g[u]|=(1<<v);
g[v]|=(1<<u);
}
for(int i=0;i<n;i++){
for(int j=0;j<(1<<i);j++){
dp[j|(1<<i)]=max(dp[j],(char)(dp[j-(j&g[i])]+1));
}
}
for(int i=0;i<(1<<n);i++){
ans+=dp[i];
}
printf("%d\n",ans);
return 0;
}
F、 maximum clique 1 (最大团)
题意:
给出一个序列,输出最大的子集其中两两的二进制位至少有两位不同。
分析:
首先对于最大团的题目,要先想到是转换成最大独立子集来考虑(因为补图的最大独立子集即为原图的最大团)
最大团(图中最大的完全子图)最大独立子集(最大的点集其中两两没有边相连)
定理:最大独立子集等于n-最大匹配。
考虑这个题:将题目条件转化为补集的条件即为计算恰有一个二进制位相同的数。
那么我们可以利用这个性质进行建图计算最大匹配数即可。
题目还有个要求是输出最大独立子集。(这块我也看了别人代码好久才有点理解)
首先考虑几点:
1、肯定是二进制位数是奇数和二进制位数为偶数的有边相连。
2、如果二进制是偶数的数多的话,那么对于偶数肯定是s=1,t=0,对于奇数正好相反。
3、如果二进制是奇数的数多的话,那么对于偶数数肯定是s=0,t=1,对于奇数正好相反。
那么根据这三点就可以判断出最大独立子集了。
(以上想法不是很成熟,准备补完多校再刷下这快的专题,若有不对希望大佬批评指正。)
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=5005;
int a[maxn];
int match[maxn];
bool s[maxn];
bool t[maxn];
bool b[maxn];
vector<int> vec[maxn];
bool dfs(int u){
s[u]=1;
for(auto v:vec[u]){
if(t[v]==0){
t[v]=1;
if(match[v]==0||dfs(match[v])){
match[v]=u;
return 1;
}
}
}
return 0;
}
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
rep(i,1,n){
rep(j,i+1,n){
if(__builtin_popcount(a[i]^a[j])==1) {
vec[i].push_back(j);
vec[j].push_back(i);
}
}
}
mm(match,0);
for(int i=1;i<=n;i++){
rep(j,1,n) t[j]=0;
if(dfs(i)) b[i]=1;
}
mm(s,0);
mm(t,0);
for(int i=1;i<=n;i++){
if(!b[i]) dfs(i);
}
vector<int> ans;
for(int i=1;i<=n;i++)
if(__builtin_parity(a[i])==1&&s[i])ans.push_back(i);
for(int i=1;i<=n;i++)
if(__builtin_parity(a[i])==0&&!t[i])ans.push_back(i);
printf("%d\n",ans.size());
for(auto x:ans){
printf("%d ",a[x]);
}
return 0;
}
G 、subsequence 1 (DP+组合计数)
题意:
给出两个数字组成的字符串,计算第一个字符串当中有多少个子序列大于第二个字符串,不能有前导零。
分析:
对于长度大于第二个序列的直接用组合数计算即可,那么考虑长度相同的子序列的情况,因为前缀可能出现相同的情况,所以这部分用DP进行递推计算;
表示第一个字符串的前i位有多少个子序列与第二个字符串的前j位相同。
那么很容易得到递推式:
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const ll mod=998244353;
const int maxn=3005;
ll c[maxn][maxn];
ll dp[maxn][maxn];
char s[maxn],t[maxn];
void init(){
c[0][0]=1ll;
for(int i=0;i<maxn;i++){
c[i][0]=c[i][i]=1ll;
}
for(int i=1;i<maxn;i++){
for(int j=1;j<i;j++){
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
init();
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
scanf("%s%s",s+1,t+1);
ll ans=0;
for(int i=0;i<=n;i++){
dp[i][0]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=min(i,m);j++){
dp[i][j]=dp[i-1][j];
if(s[i]==t[j]) dp[i][j]=(dp[i][j]+dp[i-1][j-1])%mod;
if(s[i]>t[j]) ans=(ans+dp[i-1][j-1]*c[n-i][m-j]%mod)%mod;
}
}
for(int i=1;i<=n;i++){
if(s[i]=='0') continue;
for(int j=m;j<=n-i;j++){
(ans+=c[n-i][j])%=mod;
}
}
printf("%lld\n",ans);
}
return 0;
}
H 、subsequence 2 (拓扑排序)
题意:
给出一个字符串,然后再给出一个原串删除一些字符后的字符串,然后给出这么一系列的字符串,求原串是什么。
分析:
没想到是拓扑排序,不过看了题解后也感觉很顺其自然是拓扑排序。
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e5;
int in[28*maxn];
int num[30];
vector<int> g[28*maxn];
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int n,m;
cin>>n>>m;
for(int i=0;i<m*(m-1)/2;i++){
string s,t;
int len;
cin>>s>>len;
if(!len){
continue;
}
cin>>t;
int a=0,b=0,cur=0,now;
for(int i=0;i<len;i++){
if(t[i]==s[0]){
a++;
now=(t[i]-'a')*maxn+a;
}else if(t[i]==s[1]){
b++;
now=(t[i]-'a')*maxn+b;
}
if(cur){
in[now]++;
g[cur].pb(now);
}
cur=now;
}
num[s[0]-'a']=a;
num[s[1]-'a']=b;
}
queue<int> q;
for(int i=0;i<26;i++){
if(num[i]&&in[i*maxn+1]==0){
q.push(i*maxn+1);
}
}
string ans;
while(!q.empty()){
int fro=q.front();q.pop();
ans.push_back((fro-1)/maxn+'a');
for(auto x:g[fro]){
in[x]--;
if(in[x]==0) q.push(x);
}
}
if(ans.size()!=n ) cout<<"-1"<<endl;
else cout<<ans<<endl;
return 0;
}
I 、three points 1 (计算几何)
题意:
给出三角形的三条边,拼成一个三角形并且这个三角形的三个点的坐标都在给的矩形内。
分析:
因为如果三角形能放下矩形内,那么一定可以经过平移然后三角的点在矩形的顶点上,那么可以枚举每个三角形的形态,进行判断即可。
#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-8;
double w,h;
pid p[5];
int cmp(double x){
if(fabs(x)<eps) return 0;
if(x>0) return 1;
return -1;
}
bool judge(double a,double b,double c,int o,int t,int s){
p[o]={0.0,0.0};
double ang=acos(1.0*(a*a+c*c-b*b)/(2.0*a*c));
if(a<=w) p[t]={a,0.0};
else p[t]={w,sqrt(1.0*a*a-w*w)},ang+=acos(1.0*w/a);
p[s]={c*cos(ang),c*sin(ang)};
if(cmp(p[t].fi-w)<=0&&cmp(p[t].se-h)<=0&&cmp(p[s].fi-w)<=0&&cmp(p[s].se-h)<=0&&cmp(p[s].fi)>=0&&cmp(p[s].se)>=0){
printf("%.12f %.12f %.12f %.12f %.12f %.12f\n",p[1].fi,p[1].se,p[2].fi,p[2].se,p[3].fi,p[3].se);
return 1;
}
return 0;
}
int main(){
#ifdef io
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
double a,b,c;
int T;
scanf("%d",&T);
while(T--){
scanf("%lf%lf%lf%lf%lf",&w,&h,&a,&b,&c);
if(judge(a,c,b,1,2,3))continue;
if(judge(b,c,a,1,3,2))continue;
if(judge(c,b,a,2,3,1))continue;
if(judge(a,b,c,2,1,3))continue;
if(judge(c,a,b,3,2,1))continue;
if(judge(b,a,c,3,1,2))continue;
}
return 0;
}