CSP模拟8

.....给自己考傻了,有点开摆的感觉。

A. Coprime 2

题目链接

比较的简单,和洛谷的月赛题差不多。

先把质数都筛出来,然后标记 n 个数的质因子。(预处理)

然后把询问的数枚举,查质因子,然后就没了。

复杂度 O(nlog2n).

T1
#include <iostream>
#include <cstdio>

#define rint register int 

const int MAXN=2e6+5; 

using namespace std;

inline int read() {
    int f=1,x=0;
    char ch=getchar();
    while(ch<'0' || ch>'9') {
        if(ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0' && ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
} 

int n,m,tot; 
int a[MAXN],ans[MAXN],zs[MAXN]; 

int main() {
    
    n=read() , m=read();
    for(rint i=1;i<=n;i++) {
        int x;
        x=read();
        
        int now=x;
        for(rint j=2;j*j<=x;j++) {
            if(now%j==0) {
                zs[j]=1;
                while(now%j==0) {
                    now/=j;
                    if(zs[now]) break;
                }
            }
            if(zs[now]) break; 
        }
        if(now!=1) {
            zs[now]=1;
        }
    }
    
    ans[++tot]=1;
    
    for(rint i=2;i<=m;i++) {
        
        bool flag=1;
        int now=i;
        for(int j=2;j*j<=i;j++) {
            if(now%j==0) {
                if(zs[j]) {
                    flag=0;
                    break;
                }
                while(now%j==0) {
                    now/=j;
                }
            }
        }
        if(now!=1 && zs[now]) {
            flag=0;
        }
        
        if(flag==1) {
            ans[++tot]=i;
        }
    }
    
    printf("%d\n",tot);
    
    for(rint i=1;i<=tot;i++) {
        printf("%d\n",ans[i]);
    }
    
    return 0;
} 

 

B. Dist Max 2

题目链接

一眼二分,然后考场上不知怎么的,竟然认为二分不行,然后就寄了。

正解确实是二分。

遇事不决先排序先把其按x为关键字从小到大排序,然后就是二分答案。

设当前check的长度为 len,在来两个指针 lr ,保证两指针x的差值>=len,再在指针的两头判断,相当于把数列分为三部分,在左右两部分找答案。

复杂度 O(nlog2n);

#include <iostream>
#include <cstdio>

#define rint register int 

const int MAXN=2e6+5; 

using namespace std;

inline int read() {
    int f=1,x=0;
    char ch=getchar();
    while(ch<'0' || ch>'9') {
        if(ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0' && ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
} 

int n,m,tot; 
int a[MAXN],ans[MAXN],zs[MAXN]; 

int main() {
    
    n=read() , m=read();
    for(rint i=1;i<=n;i++) {
        int x;
        x=read();
        
        int now=x;
        for(rint j=2;j*j<=x;j++) {
            if(now%j==0) {
                zs[j]=1;
                while(now%j==0) {
                    now/=j;
                    if(zs[now]) break;
                }
            }
            if(zs[now]) break; 
        }
        if(now!=1) {
            zs[now]=1;
        }
    }
    
    ans[++tot]=1;
    
    for(rint i=2;i<=m;i++) {
        
        bool flag=1;
        int now=i;
        for(int j=2;j*j<=i;j++) {
            if(now%j==0) {
                if(zs[j]) {
                    flag=0;
                    break;
                }
                while(now%j==0) {
                    now/=j;
                }
            }
        }
        if(now!=1 && zs[now]) {
            flag=0;
        }
        
        if(flag==1) {
            ans[++tot]=i;
        }
    }
    
    printf("%d\n",tot);
    
    for(rint i=1;i<=tot;i++) {
        printf("%d\n",ans[i]);
    }
    
    return 0;
} 
View Co

 

C. Count Multiset

题目链接

考试时写了一个四维的dp方程,给我自己惊呆了。不过没写就是了。

和CSP模拟7的T3挺像的,首先不考虑m的限制,

fi,j 表示分成了 i 个数,总和为 j ,列出一个状态转移方程(也就是构造一个升序序列):

fi,j=fi-1,j-1+fi,j-i;

对于 fi-1,j-1,相当于在数列前填一个1

对于 fi,j-i,相当于把所有数抬高1

然后再考虑 m 的限制,也就是1不能随便加了,那就容斥掉 1的个数超过m的方案数

即:

fi,j=fi-1,j-1+fi,j-i-fi-(m+1),j-i

然后就无了;

复杂度 O(n2);

#include <iostream>
#include <cstdio>
 
const int MAXN=5010;
const int mod=998244353; 
 
using namespace std;

int set; 

inline int read() {
    int f=1,x=0;
    char ch=getchar();
    while(ch>'9' or ch<'0') {
        if(ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0' and ch<='9') {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return f*x;
}

int n,m,ans;
int dp[MAXN][MAXN];

int main() {
    
    n=read() , m=read();
    
    dp[0][0]=1;
    
    for(int i=1;i<=n;i++) {
        if(i<=m) {
            dp[i][i]=1;
        }
        else {
            break;
        }
    }
    
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            dp[i][j]=dp[i-1][j-1]; 
            if(j>=i) {
                dp[i][j]+=dp[i][j-i];
            }
            if(i>=m+1 and j>=i) {
                dp[i][j]-=dp[i-m-1][j-i];
                dp[i][j]%=mod;
            }
            dp[i][j]%=mod;
        }
    }
    
    for(int i=1;i<=n;i++) {
        printf("%d\n",dp[i][n]%mod);
    }
    
    
    return 0;#include <iostream>
#include <cstdio>
 
const int MAXN=5010;
const int mod=998244353; 
 
using namespace std;

int set; 

inline int read() {
    int f=1,x=0;
    char ch=getchar();
    while(ch>'9' or ch<'0') {
        if(ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0' and ch<='9') {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return f*x;
}

int n,m,ans;
int dp[MAXN][MAXN];

int main() {
    
    n=read() , m=read();

    dp[0][0]=1;
    
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            dp[i][j]+=dp[i-1][j-1]; 
            if(j>=i) {
                dp[i][j]+=dp[i][j-i];
            }
            if(i>=m+1 and j>=i) {
                dp[i][j]-=dp[i-m-1][j-i];
                dp[i][j]%=mod;
            }
            dp[i][j]%=mod;
        }
    }
    
    for(int i=1;i<=n;i++) {
        printf("%d\n",dp[i][n]%mod);
    }
    
    
    return 0;
} 
View Code

至于T4,摆了摆了,有时间再写。

posted @ 2023-07-29 09:43  Trmp  阅读(14)  评论(0编辑  收藏  举报
-->