• 【日记】12.25


    今天写了一天的题,并没有复习。

    12.25

    DP

    1.P1140相似基因:https://www.luogu.com.cn/problem/P1140

    思路:dp[i] [j]表示第一个基因的前i位和第二个基因的前j位的最大匹配,则可以从dp[i-1] [j],dp[i-1] [j-1], dp[i] [j-1]三种情况转移过来。只需要关注每次添加的字母是谁就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    const int M=1e2+50;
    struct Task{
    	int len1,len2,dp[M][M];
    	char s1[M],s2[M];
    	map<int,int> mp={{'A',1},{'C',2},{'G',3},{'T',4},{'-',5}};
    	int tr[6][6]={	{0,0,0,0,0,0},
    					{0,5,-1,-2,-1,-3},
    					{0,-1,5,-3,-2,-4},
    					{0,-2,-3,5,-2,-2},
    					{0,-1,-2,-2,5,-1},
    					{0,-3,-4,-2,-1,0}};
    	void init(){
    		scanf("%d%s%d%s",&len1,s1+1,&len2,s2+1);
    		for(int i=1;i<=len1;++i)
    			dp[i][0]=dp[i-1][0]+tr[mp[s1[i]]][mp['-']];
    		for(int i=1;i<=len2;++i)
    			dp[0][i]=dp[0][i-1]+tr[mp[s2[i]]][mp['-']];
    		for(int i=1;i<=len1;++i)
    			for(int j=1;j<=len2;++j)
    				dp[i][j]=-1e9;
    	}
    	void run(){
    		init();
    		for(int i=1;i<=len1;++i)
    			for(int j=1;j<=len2;++j)
    				dp[i][j]=max(dp[i][j],dp[i-1][j]+tr[mp[s1[i]]][mp['-']]),
    				dp[i][j]=max(dp[i][j],dp[i][j-1]+tr[mp[s2[j]]][mp['-']]),
    				dp[i][j]=max(dp[i][j],dp[i-1][j-1]+tr[mp[s1[i]]][mp[s2[j]]]);
    		printf("%d
    ",dp[len1][len2]);
    	}
    }t;
    int main(){
    	t.run();
    	return 0;
    }
    

    数学

    1.P2158:洛谷仪仗队

    题解:首先可以只观察一半,对第二列,能看到1个,第三列看到2个,实际上就是(3,1)(3,2)这里面两个数互质的个数,所以其实就是phi的前缀和*2+1。

    #include<bits/stdc++.h>
    using namespace std;
    const int M=1e5+20;
    #define LL long long
    int vis[M],prime[M],cnt;
    LL phi[M];
    void get(int n){
        phi[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i])
                prime[++cnt]=i,phi[i]=i-1;
            for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0){
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
        for(int i=1;i<=n;i++)
            phi[i]+=phi[i-1];
    }
    int main(){
    	int n;
    	scanf("%d",&n);
    	get(n);
    	if (n==1)
    		printf("0
    ");
    	else
    		printf("%lld
    ",phi[n-1]*2+1);
    	return 0;
    }
    

    2.P1582

    题意:有n个瓶子,每个都有1L水,每次只能选择两个水相同的瓶子,合成一个,扔掉空瓶子。现在需要保留最多k个瓶子,问需要至少购买多少个新的有1L水的新瓶子?

    思路:水瓶里的水的体积一定是2的幂,所以n瓶水最少需要的瓶子数,等于n的二进制拆分中1的个数。那么如何减少1的个数呢?答案是需要购买lowbit(n)个新瓶子,然后合成,进位,可能会减少1的数量。

    #include<bits/stdc++.h>
    using namespace std;
    int get_num(int x){
    	int ans=0;
    	for(int i=0;i<=31;++i)
    		ans+=((x>>i)&1);
    	return ans;
    }
    inline int lowbit(int x){return x&-x;}
    int main(){
    	int n,k;
    	scanf("%d%d",&n,&k);
    	int ans=0;
    	while(get_num(n)>k)
    		ans+=lowbit(n),n+=lowbit(n);
    	printf("%d
    ",ans);
    	return 0;	
    }
    

    分块&&莫反

    1.BZOJ1257:计算k%1+k%2+...+k%n的和。1e9。

    思路:最简单的分块题目,将取模拆开即可。

    [Sigma_{i=1}^{n}k-lfloorfrac{k}{i} floor*i\ n*k-Sigma_{i=1}^{n}i*lfloorfrac{k}{i} floor ]

    这里有个小技巧(学来的:https://blog.csdn.net/qq_42886072/article/details/89408397),特判0和超过n的情况。

    #include<bits/stdc++.h>
    using namespace std;
    struct Task{
    	long long ans,n,k;
    	void init(){
    		scanf("%lld%lld",&n,&k);
    	}
    	void run(){
    		init();
    		for(int l=1,r;l<=n;l=r+1)
    			r=(k/l?min(n,k/(k/l)):n),ans+=1LL*(l+r)*(r-l+1)/2*(k/l);
    		printf("%lld
    ",n*k-ans);
    	}
    }t;
    int main(){
    	t.run();
    	return 0;
    }
    

    2.BZOJ2956:求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j。 mod19940417。

    题解:直接两个分别求,然后相乘即可。注意要把i==j的情况减掉!!!

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int P=19940417;
    struct Task{
    	int n,m;
    	void init(){
    		scanf("%d%d",&n,&m);
    	}
    	inline LL sing(int n){return 1LL*n*(n+1)/2%P;}
    	LL calc(int k,int n){//计算1-k,n/i的和
    		LL ans=0;
    		for(int l=1,r;l<=k;l=r+1)
    			r=(n/l?min(k,n/(n/l)):k),ans=(ans+(sing(r)-sing(l-1))%P*(n/l)%P)%P;
    		return ans;
    	}
    	inline LL sqr(int n){return (__int128)n*(n+1)*(2*n+1)/6%P;}
    	LL cald(int k,int n,int m){
    		LL ans=0;
    		for(int l=1,r;l<=k;l=r+1)
    			r=min(n/l?min(k,n/(n/l)):k,m/l?min(k,m/(m/l)):k),ans=(ans+(sqr(r)-sqr(l-1))%P*(n/l)%P*(m/l)%P)%P;
    		return ans;
    	}
    	void run(){
    		init();
    		int k=min(n,m);
    		printf("%lld
    ",((1LL*n*n%P-calc(n,n)+P)%P*(1LL*m*m%P-calc(m,m)+P)%P-(1LL*k*n%P*m%P-m*calc(k,n)%P+P-n*calc(k,m)%P+P+cald(k,n,m))%P+P)%P);
    	}
    }t;
    int main(){
    	t.run();
    	return 0;
    }
    

    莫比乌斯反演

    1.BZOJ1101:

    #include<bits/stdc++.h>
    using namespace std;
    const int M=5e4+20;
    #define LL long long
    LL cnt,phi[M],mu[M],prime[M],vis[M];
    void get(int n){
        phi[1]=mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i])
                prime[++cnt]=i,mu[i]=-1,phi[i]=i-1;
            for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0){
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
        for(int i=1;i<=n;i++)
            mu[i]+=mu[i-1],phi[i]+=phi[i-1];
    }
    struct Task{
    	int d,a,b;
    	void init(){
    		scanf("%d%d%d",&a,&b,&d);
    	}
    	LL cald(int k,int n,int m){
    	    LL ans=0;
    	    for(int l=1,r;l<=k;l=r+1)
    	        r=min(n/l?min(k,n/(n/l)):k,m/l?min(k,m/(m/l)):k),ans+=(mu[r]-mu[l-1])*(n/l)*(m/l);
    	    return ans;
    	}
    	void run(){
    		init();
    		printf("%lld
    ",cald(min(a/d,b/d),a/d,b/d));
    	}
    }t;
    int main(){
    	get(5e4+2);
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    2.BZOJ2301:

    思路:二维前缀和思想,ans=cgcd(b,d,k)-cgcd(a-1,d,k)-cgcd(b,c-1,k)+cgcd(a-1,c-1,k)

    #include<bits/stdc++.h>
    using namespace std;
    const int M=5e4+20;
    #define LL long long
    int cnt,mu[M],prime[M],vis[M];
    void get(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i])
                prime[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                    break;
                mu[i*prime[j]]=-mu[i];
            }
        }
        for(int i=1;i<=n;i++)
            mu[i]+=mu[i-1];
    }
    struct Task{
    	int a,b,c,d,k;
    	void init(){
    		scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    	}
    	LL cald(int k,int n,int m){
    	    LL ans=0;
    	    for(int l=1,r;l<=k;l=r+1)
    	        r=min(n/l?min(k,n/(n/l)):k,m/l?min(k,m/(m/l)):k),ans+=1LL*(mu[r]-mu[l-1])*(n/l)*(m/l);
    	    return ans;
    	}
    	inline LL cgcd(int a,int b,int d){return cald(min(a/d,b/d),a/d,b/d);}//计算i:1-a,j:1-b,gcd=d的数的个数
    	void run(){
    		init();
    		printf("%lld
    ",cgcd(b,d,k)-cgcd(a-1,d,k)-cgcd(b,c-1,k)+cgcd(a-1,c-1,k));
    	}
    }t;
    int main(){
    	get(5e4+2);
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    3.BZOJ2820:

    #include<bits/stdc++.h>
    using namespace std;
    const int M=1e7+20;
    #define LL long long
    int cnt,mu[M],prime[M],vis[M];
    LL f[M];
    void get(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i])
                prime[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                    break;
                mu[i*prime[j]]=-mu[i];
            }
        }
        for(int i=1;i<=cnt;++i)
        	for(int j=1;j*prime[i]<=n;++j)
        		f[j*prime[i]]+=mu[j];
        for(int i=1;i<=n;++i)
        	f[i]+=f[i-1];
    }
    struct Task{
    	int n,m;
    	void init(){
    		scanf("%d%d",&n,&m);
    	}
    	LL cald(int k,int n,int m){
    	    LL ans=0;
    	    for(int l=1,r;l<=k;l=r+1)
    	        r=min(n/l?min(k,n/(n/l)):k,m/l?min(k,m/(m/l)):k),ans+=(f[r]-f[l-1])*(n/l)*(m/l);
    	    return ans;
    	}
    	void run(){
    		init();
    		printf("%lld
    ",cald(min(n,m),n,m));
    	}
    }t;
    int main(){
    	get(1e7+2);
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    4.P2568:

    很不理解,我预处理1e7会挂,但预处理n就不挂了,难道又是数据水?根本没有1e7的数据?

    #include<bits/stdc++.h>
    using namespace std;
    const int M=1e7+20;
    #define LL long long
    int cnt,mu[M],prime[M],vis[M];
    int f[M];
    void get(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i])
                prime[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                    break;
                mu[i*prime[j]]=-mu[i];
            }
        }
        for(int i=1;i<=cnt;++i)
        	for(int j=1;j*prime[i]<=n;++j)
        		f[j*prime[i]]+=mu[j];
        for(int i=1;i<=n;++i)
        	f[i]+=f[i-1];
    }
    struct Task{
    	int n;
    	void init(){
    		scanf("%d",&n);
    	}
    	LL cald(int k,int n,int m){
    	    LL ans=0;
    	    for(int l=1,r;l<=k;l=r+1)
    	        r=min(n/l?min(k,n/(n/l)):k,m/l?min(k,m/(m/l)):k),ans+=1LL*(f[r]-f[l-1])*(n/l)*(m/l);
    	    return ans;
    	}
    	void run(){
    		init();
    		get(n);
    		printf("%lld
    ",cald(n,n,n));
    	}
    }t;
    int main(){
    	t.run();
    	return 0;
    }
    
  • 相关阅读:
    (2)链表有哪几种分类——4
    (1)有哪几种表的实现方式——4
    链表基本操作
    多窗口
    UI线程和work线程
    模板
    (二)tensorflow-gpu2.0之自动导数
    (一)tensorflow-gpu2.0学习笔记之开篇(cpu和gpu计算速度比较)
    高阶函数及map、reduce、filter、lambda、sorted等函数的应用
    迭代器
  • 原文地址:https://www.cnblogs.com/diorvh/p/12099844.html
Copyright © 2020-2023  润新知