上紫纪念
A Gennady and a Card Game
题目大意
每个元素有两个值,现在你有个元素,问是否有一个元素与给定元素相等或者相等
题解
。
代码
# include<bits/stdc++.h>
using namespace std;
int A,B;
int a[5],b[5];
char s[5][10],qwq[10];
int main()
{
scanf("%s",qwq);
A=qwq[0],B=qwq[1];
for(int i=0;i<5;++i)
{
scanf("%s",s[i]);
a[i]=s[i][0],b[i]=s[i][1];
if(a[i]==A||B==b[i]) return printf("YES\n"),0;
}
return printf("NO\n"),0;
}
B Petr and a Combination Lock
题目大意
给定个角度,初始在位置,第次操作顺/逆时针旋转,问能否在次旋转后回到的位置
题解
最大才,状态压缩一下表示即可
代码
# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
using namespace std;
int n;
int a[21];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",&a[i]);
for(int i=0;i<(1<<n);++i)
{
int ans=0;
for(int j=0;j<n;++j)
if(i&(1<<j)) ans+=a[j];
else ans-=a[j];
if(ans%360==0) return puts("YES"),0;
}
return puts("NO"),0;
}
C Yuhao and a Parenthesis
题目大意
给定个括号序列(不一定合法),每次可以选择两个没选过的序列首尾相连合并成一个括号序列,问合并之后最多有多少个合法括号序列
题解
把'('
定为,')'
定为,可以记录每个括号序列的总和和最小前缀和,显然)...(
这种是不可能组成合法的括号序列的,分总和三种情况讨论一下即可
代码
# include<iostream>
# include<cstring>
# include<cstdio>
# include<map>
# include<algorithm>
using namespace std;
const int MAX=1e5+5;
int n,ans;
char a[MAX*5];
map<int,int> ma;
int main()
{
scanf("%d",&n);
for(int i=1,_n,w,_w;i<=n;++i)
{
scanf("%s",a),_n=strlen(a),w=0,_w=1e9;
for(int j=0;j<_n;++j)
{
if(a[j]=='(') ++w;
else --w;
_w=min(_w,w);
}
if(!w&&_w>=0)
{
if(ma[w]) --ma[w],++ans;
else ++ma[w];
}
if(w>0&&_w>=0)
{
if(ma[-w]) --ma[-w],++ans;
else ++ma[w];
}
if(w<0&&_w>=w)
{
if(ma[-w]) --ma[-w],++ans;
else ++ma[w];
}
}
return printf("%d",ans),0;
}
D Makoto and a Blackboard
题目大意
给定两个数,每次随机选择的某个因子使得,问操作次后的期望值
题解
如果(为素数)就可以直接暴力枚举然后了
因为(对质因子分解),所以答案为,具体为什么不会证……听说好像是跟积性函数有关?管他呢A了就行了
代码
# include<iostream>
# include<cstring>
# include<cstdio>
# include<cmath>
# include<map>
# include<algorithm>
# define LL long long
using namespace std;
const int MAX=1e4+5,mod=1e9+7;
LL n;
int k,cnt,ans=1;
LL qwq[MAX];
int f[101][MAX];
map<LL,int> ma;
int Pow(LL a,int b)
{
int ans=1;
a%=mod;
for(;b;b>>=1,a=1ll*a*a%mod)
if(b&1) ans=1ll*a*ans%mod;
return ans;
}
int dfs(LL A,int x,int t=0)
{
if(f[x][t]) return f[x][t];
if(t==k) return Pow(A,x);
int ans=0;
for(int i=0;i<=x;++i)
ans=(ans+dfs(A,i,t+1))%mod;
return f[x][t]=1ll*ans*Pow(x+1,mod-2)%mod;
}
int main()
{
cin>>n>>k;
for(int i=2;i<=sqrt(n);++i)
while(n%i==0)
{
if(++ma[i]==1) qwq[++cnt]=i;
n/=i;
}
if(n!=1) if(++ma[n]==1) qwq[++cnt]=n;
for(int i=1;i<=cnt;++i)
memset(f,0,sizeof(f)),ans=1ll*ans*dfs(qwq[i],ma[qwq[i]])%mod;
return printf("%d",ans),0;
}
E Egor and an RPG game
F Alex and a TV Show
题目大意
给定个初始为空的集合(可重集),有四个操作:
- 给定集合位置和一个数,然后
- 给定集合位置,然后
- 给定集合位置,然后
- 给定集合位置和一个数,然后输出集合中有多少个,答案
题解
用表示集合中的倍数出现次数的奇偶性,可以用bitset
维护
因为值域才,操作一可以直接枚举修改
操作二发现都是的时候答案是,都是的时候答案是,一个是的时候答案是,所以就是一个异或操作
操作三发现都是的时候答案是,都是的时候答案是,一个是的时候答案是,所以就是一个与操作
操作四可以莫比乌斯反演一下:
设表示集合中的出现次数,则有
因为只有两种取值,所以的值为和没有区别,预处理一下即可
代码
# include<iostream>
# include<cstring>
# include<cstdio>
# include<bitset>
# include<cmath>
# include<algorithm>
using namespace std;
const int MAX=1e5+5,N=7e3+5;
int n,q,tot;
int u[N],pm[N];
bool use[N];
bitset<N> a[MAX],b[N],w[N];
int read()
{
int x(0);
char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);x=x*10+ch-48,ch=getchar());
return x;
}
int main()
{
n=read(),q=read(),u[1]=1;
for(int i=2;i<N;++i)
{
if(!use[i]) pm[++tot]=i,u[i]=-1;
for(int j=1;j<=tot&&i*pm[j]<N;++j)
{
use[i*pm[j]]=1;
if(i%pm[j]==0) break;
u[i*pm[j]]=-u[i];
}
}
for(int i=1,x;i<N;++i)
{
x=sqrt(i);
for(int j=1;j<=x;++j)
if(i%j==0) w[i][j]=w[i][i/j]=1;
}
for(int i=1;i<N;++i)
for(int j=i;j<N;j+=i)
if(u[j/i]) b[i][j]=1;
for(int i=1,op,x,y,z;i<=q;++i)
{
op=read(),x=read(),y=read();
if(op==1) a[x]=w[y];
else if(op==2) z=read(),a[x]=a[y]^a[z];
else if(op==3) z=read(),a[x]=a[y]&a[z];
else if(op==4) printf("%d",(a[x]&b[y]).count()%2);
}
return 0;
}