2023.2.22模拟赛
T1
题意:
构造一个以1开头,由\(n\)个1和\(m\)个0组成的01串,使得其表示的二进制数可以被三整除,求其最大值和最小值。
思路:
分讨:
1.n为偶,m为偶,最大值\(\overset{n}{1\dots 1} \overset{m}{0\dots 0}\),最小值\(1\overset{m}{0\dots 0}\overset{n-1}{1\dots 1}\)
2.n为偶,m为奇,最大值\(\overset{n}{1\dots 1} \overset{m}{0\dots 0}\),最小值\(1\overset{m-1}{0\dots 0}10\overset{n-2}{1\dots 1}\)
3.n为奇,m为偶,最大值\(\overset{n-2}{1\dots 1}0101\overset{m-2}{0\dots 0}\),最小值\(1\overset{m-1}{0\dots 0}10\overset{n-2}{1\dots 1}\)
4.n为奇,m为奇,最大值\(\overset{n-2}{1\dots 1}0101\overset{m-2}{0\dots 0}\),最小值\(1\overset{m-2}{0\dots 0}1010\overset{n-3}{1\dots 1}\)
代码:
#include<iostream>
#include<cstdio>
using namespace std;
int kd(){
int x=0,f=1;
char a=getchar();
while(a<'0'||a>'9'){
if(a=='-'){
f=-1;
}
a=getchar();
}
while(a>='0'&&a<='9'){
x=x*10+a-'0';
a=getchar();
}
return x*f;
}
int t;
int n,m;
int main(){
t=kd();
while(t--){
n=kd();m=kd();
if(n<=1){
printf("-1");
}
else{
if(n%2==0){
for(int i=1;i<=n;i++){
printf("1");
}
for(int i=1;i<=m;i++){
printf("0");
}
}
else{
if(m<=1){
printf("-1");
}
else{
for(int i=1;i<=n-2;i++){
printf("1");
}
printf("0101");
for(int i=1;i<=m-2;i++){
printf("0");
}
}
}
}
printf("\n");
if(n<=1){
printf("-1");
}
else{
if(n%2==0){
printf("1");
if((n+m)%2==0){
for(int i=1;i<=m;i++){
printf("0");
}
for(int i=1;i<=n-1;i++){
printf("1");
}
}
else{
for(int i=1;i<=m-1;i++){
printf("0");
}
printf("10");
for(int i=1;i<=n-2;i++){
printf("1");
}
}
}
else{
if((n+m)%2==1){
if(m==0){
printf("-1");
}
else{
printf("1");
for(int i=1;i<=m-1;i++){
printf("0");
}
printf("10");
for(int i=1;i<=n-2;i++){
printf("1");
}
}
}
else{
if(m==1){
printf("-1");
}
else{
printf("1");
for(int i=1;i<=m-2;i++){
printf("0");
}
printf("1010");
for(int i=1;i<=n-3;i++){
printf("1");
}
}
}
}
}
printf("\n");
}
return 0;
}
T2
题意:
给定一个数\(n\),计数\(n\)的排列满足\(p_{i}\)的因子个数等于\(i\)的因子个数。\(t\)组询问,答案对\(500009\)取模。\(n<=1e9\)。
思路:
首先考虑线性筛因子个数\(C_{i}=\prod (a_{k}+1)\):
1.\(i\)为质数。因子个数为2。
2.\(i=j\times s\) (\(s\)为质数),且 \(j\)是 \(s\)的倍数。因子个数为\(C_{j}\times 2\)。
3.\(i=j\times s\) (\(s\)为质数),且 \(s\mid j\),\(C_{i}=\frac{C_{j}\times (a_{s}+1+1)}{a_{s}+1}=2\times C_{j}-\frac{C_{j}\times a_{s}}{a_{s}+1}=2\times C_{j}-C_{\frac{j}{s}}\),所以因子个数为\(2\times C_{j}-C_{\frac{j}{s}}\)。
这样就可以统计出\(C_{i}=k\)的个数 \(B_{k}\),答案为\(\prod_{B_{k}>0} (B_{k}!)\),当\(i\ge 2229283\)时,因为模数,答案为0。
代码:
#include<iostream>
#define mod 500009
#define int long long
using namespace std;
int kd(){
int x=0,f=1;
char a=getchar();
while(a<'0'||a>'9'){
if(a=='-'){
f=-1;
}
a=getchar();
}
while(a>='0'&&a<='9'){
x=x*10+a-'0';
a=getchar();
}
return x*f;
}
int t;
int n;
int tong[5000010];
bool prime[5000010];
int ss[5000010];
int yz[5000010];
int f[5000010];
int g[5000010];
void shai(){
yz[1]=1;
g[1]=1;
for(int i=2;i<=5000000;i++){
if(prime[i]==0){
ss[++ss[0]]=i;
yz[i]=2;
}
tong[yz[i]]++;
f[i]=tong[yz[i]];
g[i]=g[i-1]*f[i]%mod;
for(int j=1;j<=ss[0]&&i*ss[j]<=5000000;j++){
prime[i*ss[j]]=1;
if(i%ss[j]!=0){
yz[i*ss[j]]=yz[i]*2%mod;
}
else{
yz[i*ss[j]]=((yz[i]*2-yz[i/ss[j]])%mod+mod)%mod;
break;
}
}
}
}
signed main(){
t=kd();
shai();
while(t--){
n=kd();
if(n>5000000){
printf("0\n");
}
else{
printf("%lld\n",g[n]);
}
}
return 0;
}
T3
题意:
\(n\)个点\((X,Y)\),\(q\)个直角边与x轴和y轴平行的等腰直角三角形\((x,y,d)\),求每个等腰直角三角形覆盖的点有多少个。
思路:
容斥。
$\overset{X\ge x,Y\ge y,X+Y\le x+y+d}{7} =\overset{n}{(1+2+3+4+5+6+7)} -\overset{X<x}{(1+2+3)} -\overset{Y<y}{(3+4+5)} -\overset{X+Y>x+y+d}{(5+6+1)} +\overset{X<x,X+Y>x+y+d}{1} +\overset{X<x,Y<y}{3} +\overset{Y<y,X+Y>x+y+d}{5} $
\(1,3,5\)用二维数点求。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int kd(){
int x=0,f=1;
char a=getchar();
while(a<'0'||a>'9'){
if(a=='-'){
f=-1;
}
a=getchar();
}
while(a>='0'&&a<='9'){
x=x*10+a-'0';
a=getchar();
}
return x*f;
}
int n,q;
struct node{
int x,y;
int d;
int id;
}b[1000010],a[1000010];
int ans[1000010];
bool cmp(node x,node y){
return x.x<y.x;
}
bool cnp(node x,node y){
return x.y<y.y;
}
bool cup(node x,node y){
return x.d>y.d;
}
int c[3000010];
int lowbit(int x){
return x&(-x);
}
void add(int x,int k){
for(;x<=3000000;x+=lowbit(x)){
c[x]+=k;
}
}
int getsum(int x){
int sum=0;
for(;x;x-=lowbit(x)){
sum+=c[x];
}
return sum;
}
int main(){
n=kd();q=kd();
for(int i=1;i<=n;i++){
a[i].x=kd();a[i].y=kd();
a[i].d=a[i].x+a[i].y;
}
for(int i=1;i<=q;i++){
b[i].x=kd();b[i].y=kd();b[i].d=b[i].x+b[i].y+kd();
b[i].id=i;
ans[i]=n;
}
sort(a+1,a+n+1,cmp);
sort(b+1,b+q+1,cmp);
int i=1;
for(int j=1;j<=q;j++){
while(i<=n&&a[i].x<b[j].x){
i++;
}
ans[b[j].id]-=i-1;
}
i=1;
for(int j=1;j<=q;j++){
while(i<=n&&a[i].x<b[j].x){
add(a[i].y,1);
i++;
}
ans[b[j].id]+=getsum(b[j].y-1);
}
for(i=i-1;i>=1;i--){
add(a[i].y,-1);
}
i=1;
for(int j=1;j<=q;j++){
while(i<=n&&a[i].x<b[j].x){
add(a[i].d,1);
i++;
}
ans[b[j].id]+=i-1-getsum(b[j].d);
}
for(i=i-1;i>=1;i--){
add(a[i].d,-1);
}
sort(a+1,a+n+1,cnp);
sort(b+1,b+q+1,cnp);
i=1;
for(int j=1;j<=q;j++){
while(i<=n&&a[i].y<b[j].y){
i++;
}
ans[b[j].id]-=i-1;
}
i=1;
for(int j=1;j<=q;j++){
while(i<=n&&a[i].y<b[j].y){
add(a[i].d,1);
i++;
}
ans[b[j].id]+=i-1-getsum(b[j].d);
}
for(i=i-1;i>=1;i--){
add(a[i].d,-1);
}
sort(a+1,a+n+1,cup);
sort(b+1,b+q+1,cup);
i=1;
for(int j=1;j<=q;j++){
while(i<=n&&a[i].d>b[j].d){
i++;
}
ans[b[j].id]-=i-1;
}
for(int j=1;j<=q;j++){
cout<<ans[j]<<endl;
}
return 0;
}
T4
题意:
计数,长度为\(n\)的字符序列\(a_{i}\in [x_{i},y_{i}]\),\(m\)组限制,\((\sum_{k=l_{j}}^{r_{j}} a_{k})\mod 2=s_{j}\)
思路:
\(qian_{i}=(\sum_{k=1}^{i} a_{k})\mod 2\)
将 \(l_{j}-1\)和\(r_{j}\)建边,当\(qian_{l_{j}-1}\)确定时,\(qian_{r_{j}}\)也一定确定,可以对搜索进行剪枝。
当某个\(i\)与其它位置没有连边时,这不会影响到其他位置的\(qian\),这样就可以对这个位置进行DP。
\(dp_{u,0/1,0/1}\)表示第\(u\)个位置\(qian_{u}=0/1\),\(a_{u}\mod 2=0/1\)
用\(ans_{u,0/1,0/1,i}\)维护最小字典序序列。
代码:
#include<iostream>
#define mod 1000000007
#define int long long
using namespace std;
int kd(){
int x=0,f=1;
char a=getchar();
while(a<'0'||a>'9'){
if(a=='-'){
f=-1;
}
a=getchar();
}
while(a>='0'&&a<='9'){
x=x*10+a-'0';
a=getchar();
}
return x*f;
}
int n,m;
struct node{
int x,y;
int w[2];
}a[50];
struct nod{
int to;
int nxt;
int val;
}edge[210];
int head[50],tot;
void addedge(int u,int v,int w){
edge[++tot].to=v;
edge[tot].nxt=head[u];
edge[tot].val=w;
head[u]=tot;
}
int dui[50];
int cnt[50];
int qian[50];
int dp[50][2][2];
int ans[50][2][2][50];
int pd(int u,int i,int j,int k,int h){
for(int w=u+1;w<=n;w++){
if(ans[u+1][i][j][w]<ans[u][k][h][w]){
return 1;
}
if(ans[u+1][i][j][w]>ans[u][k][h][w]){
return 0;
}
}
return 1;
}
void dfs(int u){
if(u>n){
return ;
}
for(int j=1;j<=n;j++){
ans[u][0][0][j]=a[j].y;
ans[u][0][1][j]=a[j].y;
ans[u][1][0][j]=a[j].y;
ans[u][1][1][j]=a[j].y;
}
dp[u][0][0]=0;
dp[u][0][1]=0;
dp[u][1][0]=0;
dp[u][1][1]=0;
if(cnt[u]==0){
dfs(u+1);
if(qian[u+1]!=1){
dp[u][0][0]=(dp[u][0][0]+dp[u+1][0][0]*a[u].w[0]%mod)%mod;
if(dp[u+1][0][0]>0&&pd(u,0,0,0,0)){
for(int j=u+1;j<=n;j++){
ans[u][0][0][j]=ans[u+1][0][0][j];
}
ans[u][0][0][u]=(a[u].x+1)/2*2;
}
dp[u][0][1]=(dp[u][0][1]+dp[u+1][0][0]*a[u].w[1]%mod)%mod;
if(dp[u+1][0][0]>0&&pd(u,0,0,0,1)){
for(int j=u+1;j<=n;j++){
ans[u][0][1][j]=ans[u+1][0][0][j];
}
ans[u][0][1][u]=a[u].x/2*2+1;
}
dp[u][1][0]=(dp[u][1][0]+dp[u+1][0][1]*a[u].w[0]%mod)%mod;
if(dp[u+1][0][1]>0&&pd(u,0,1,1,0)){
for(int j=u+1;j<=n;j++){
ans[u][1][0][j]=ans[u+1][0][1][j];
}
ans[u][1][0][u]=(a[u].x+1)/2*2;
}
dp[u][1][1]=(dp[u][1][1]+dp[u+1][0][1]*a[u].w[1]%mod)%mod;
if(dp[u+1][0][1]>0&&pd(u,0,1,1,1)){
for(int j=u+1;j<=n;j++){
ans[u][1][1][j]=ans[u+1][0][1][j];
}
ans[u][1][1][u]=a[u].x/2*2+1;
}
}
if(qian[u+1]!=0){
dp[u][0][0]=(dp[u][0][0]+dp[u+1][1][1]*a[u].w[0]%mod)%mod;
if(dp[u+1][1][1]>0&&pd(u,1,1,0,0)){
for(int j=u+1;j<=n;j++){
ans[u][0][0][j]=ans[u+1][1][1][j];
}
ans[u][0][0][u]=(a[u].x+1)/2*2;
}
dp[u][0][1]=(dp[u][0][1]+dp[u+1][1][1]*a[u].w[1]%mod)%mod;
if(dp[u+1][1][1]>0&&pd(u,1,1,0,1)){
for(int j=u+1;j<=n;j++){
ans[u][0][1][j]=ans[u+1][1][1][j];
}
ans[u][0][1][u]=a[u].x/2*2+1;
}
dp[u][1][0]=(dp[u][1][0]+dp[u+1][1][0]*a[u].w[0]%mod)%mod;
if(dp[u+1][1][0]>0&&pd(u,1,0,1,0)){
for(int j=u+1;j<=n;j++){
ans[u][1][0][j]=ans[u+1][1][0][j];
}
ans[u][1][0][u]=(a[u].x+1)/2*2;
}
dp[u][1][1]=(dp[u][1][1]+dp[u+1][1][0]*a[u].w[1]%mod)%mod;
if(dp[u+1][1][0]>0&&pd(u,1,0,1,1)){
for(int j=u+1;j<=n;j++){
ans[u][1][1][j]=ans[u+1][1][0][j];
}
ans[u][1][1][u]=a[u].x/2*2+1;
}
}
return ;
}
int zhan[50],top;
int p;
if(qian[u]!=1){
p=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(qian[v]!=-1&&qian[v]!=0^edge[i].val){
p=1;
}
}
if(p==0){
top=0;
int t=qian[u];
qian[u]=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(qian[v]==-1){
qian[v]=qian[u]^edge[i].val;
zhan[++top]=v;
}
}
dfs(u+1);
if(qian[u+1]!=1){
dp[u][0][0]=(dp[u][0][0]+dp[u+1][0][0]*a[u].w[0]%mod)%mod;
if(dp[u+1][0][0]>0&&pd(u,0,0,0,0)){
for(int j=u+1;j<=n;j++){
ans[u][0][0][j]=ans[u+1][0][0][j];
}
ans[u][0][0][u]=(a[u].x+1)/2*2;
}
dp[u][0][1]=(dp[u][0][1]+dp[u+1][0][0]*a[u].w[1]%mod)%mod;
if(dp[u+1][0][0]>0&&pd(u,0,0,0,1)){
for(int j=u+1;j<=n;j++){
ans[u][0][1][j]=ans[u+1][0][0][j];
}
ans[u][0][1][u]=a[u].x/2*2+1;
}
}
if(qian[u+1]!=0){
dp[u][0][0]=(dp[u][0][0]+dp[u+1][1][1]*a[u].w[0]%mod)%mod;
if(dp[u+1][1][1]>0&&pd(u,1,1,0,0)){
for(int j=u+1;j<=n;j++){
ans[u][0][0][j]=ans[u+1][1][1][j];
}
ans[u][0][0][u]=(a[u].x+1)/2*2;
}
dp[u][0][1]=(dp[u][0][1]+dp[u+1][1][1]*a[u].w[1]%mod)%mod;
if(dp[u+1][1][1]>0&&pd(u,1,1,0,1)){
for(int j=u+1;j<=n;j++){
ans[u][0][1][j]=ans[u+1][1][1][j];
}
ans[u][0][1][u]=a[u].x/2*2+1;
}
}
qian[u]=t;
for(int i=1;i<=top;i++){
qian[zhan[i]]=-1;
}
}
}
if(qian[u]!=0){
p=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(qian[v]!=-1&&qian[v]!=1^edge[i].val){
p=1;
}
}
if(p==0){
top=0;
int t=qian[u];
qian[u]=1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(qian[v]==-1){
qian[v]=qian[u]^edge[i].val;
zhan[++top]=v;
}
}
dfs(u+1);
if(qian[u+1]!=1){
dp[u][1][0]=(dp[u][1][0]+dp[u+1][0][1]*a[u].w[0]%mod)%mod;
if(dp[u+1][0][1]>0&&pd(u,0,1,1,0)){
for(int j=u+1;j<=n;j++){
ans[u][1][0][j]=ans[u+1][0][1][j];
}
ans[u][1][0][u]=(a[u].x+1)/2*2;
}
dp[u][1][1]=(dp[u][1][1]+dp[u+1][0][1]*a[u].w[1]%mod)%mod;
if(dp[u+1][0][1]>0&&pd(u,0,1,1,1)){
for(int j=u+1;j<=n;j++){
ans[u][1][1][j]=ans[u+1][0][1][j];
}
ans[u][1][1][u]=a[u].x/2*2+1;
}
}
if(qian[u+1]!=0){
dp[u][1][0]=(dp[u][1][0]+dp[u+1][1][0]*a[u].w[0]%mod)%mod;
if(dp[u+1][1][0]>0&&pd(u,1,0,1,0)){
for(int j=u+1;j<=n;j++){
ans[u][1][0][j]=ans[u+1][1][0][j];
}
ans[u][1][0][u]=(a[u].x+1)/2*2;
}
dp[u][1][1]=(dp[u][1][1]+dp[u+1][1][0]*a[u].w[1]%mod)%mod;
if(dp[u+1][1][0]>0&&pd(u,1,0,1,1)){
for(int j=u+1;j<=n;j++){
ans[u][1][1][j]=ans[u+1][1][0][j];
}
ans[u][1][1][u]=a[u].x/2*2+1;
}
}
qian[u]=t;
for(int i=1;i<=top;i++){
qian[zhan[i]]=-1;
}
}
}
}
signed main(){
n=kd();m=kd();
for(int i=1;i<=n;i++){
a[i].x=kd();a[i].y=kd();
qian[i]=-1;
cnt[i]=0;
a[i].w[1]=(a[i].y-a[i].x+1)/2;
a[i].w[0]=(a[i].y-a[i].x+1)/2;
if(a[i].x%2==a[i].y%2){
if(a[i].x%2==1){
a[i].w[1]++;
}
else{
a[i].w[0]++;
}
}
}
cnt[0]=0;
a[0].w[0]=1;
a[0].w[1]=1;
qian[n+1]=-1;
for(int i=1;i<=m;i++){
int u,v,w;
u=kd();v=kd();w=kd();
u--;
cnt[u]++;
cnt[v]++;
addedge(u,v,w);
}
for(int i=head[0];i;i=edge[i].nxt){
int v=edge[i].to;
qian[v]=edge[i].val;
}
dp[n+1][0][0]=1;
dp[n+1][1][0]=1;
dfs(0);
cout<<dp[0][0][0]<<endl;
if(dp[0][0][0]==0){
cout<<-1;
}
else{
for(int i=1;i<=n;i++){
cout<<ans[0][0][0][i]<<" ";
}
}
return 0;
}