数论+dp部分代码

数论

\(G\)题 【模板】筛法

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e8+10;
int  prime[maxn];
bool   vis[maxn]; 
int main(){ 
	int cnt=0;
	int n,q;
	cin>>n>>q;
	for(int i=2;i<=n;i++)
	{
		if(vis[i]==0)
		prime[++cnt]=i;
		
		for(int j=1;j<=cnt&&prime[j]*i<=n;j++)
		{
				vis[prime[j]*i]=1;
				if(i%prime[j]==0)
					break;
		}
	}

	int x;
	for(int i=1;i<=q;++i)
		cin>>x,cout<<prime[x]<<"\n";
	system("pause");
	return 0;

}//欧拉筛 

\(L\)题 【模板】费马小定理

#include<bits/stdc++.h>
#define int long long
using namespace std;
int qpow(int a,int b,int p)
{ 
    int res=1,temp=a;
    while(b)
    {
        if(b&1) res=1ll*res*temp%p; 

        temp=1ll*temp*temp%p;
        b>>=1;
    } 
    
    return res;
}

signed main()
{
    int a,b,p;
    cin>>a>>b>>p;
	
//	b%=p-1; 
    cout<<qpow(a,b,p);
    system("pause");
    return 0;
}

报数

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int n=1e7+10;
bool tong[n]; 
int arr[n];
bool cf(int x)
{
	while(x)
	{
		if(x%10==7) return 1;
		x/=10;
	}
	return 0;
}
signed main()
{
// 	freopen("number.in","r",stdin);
// 	freopen("number.ans","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	//初始化  
	for(int i=1;i<=n;++i)
		if(cf(i))
			for(int j=1;i*j<=n;++j)
				tong[j*i]=1;
	
	int cnt=0;
	for(int i=1;i<=n;++i)
		if(tong[i]==0) arr[++cnt]=i;
		
	int t;
	cin>>t;
	
	while(t--)
	{
		int x;
		cin>>x;
		
		int id=lower_bound(arr+1,arr+cnt+1,x)-arr;
		if(arr[id]!=x) cout<<-1<<"\n";
		else cout<<arr[id+1]<<"\n";
	}	
}

dp

\(A\)题 能量项链

#include<bits/stdc++.h>
using namespace std;
int head[310];//头标记
int tail[310];//尾标记
int f[310][310];//f[i][j]:[i,j]区间中合并的最大价值
int main()
{
    int n;
    cin>>n;


    //根据题意赋值头标记和尾标记(将链n复制拼接为2n长度)
    for(int i=1;i<=n;++i)   
        cin>>head[i];

    for(int i=n+1;i<=2*n;++i)
        head[i]=head[i-n];

    for(int i=1;i<2*n;++i)
        tail[i]=head[i+1];
    
    tail[2*n]=head[1];


    for(int len=1;len<n;++len)//枚举区间[i,j]的长度
    {   
        for(int i=1,j=i+len;i+len<=2*n;++i,++j)//枚举起始点i和区间结尾j
            /*枚举区间[i,j]*/
            for(int k=i;k<j;++k)//枚举中转点 
                f[i][j]=max(f[i][k]+f[k+1][j]+head[i]*tail[k]*tail[j],f[i][j]);//区间dp:能合并就尝试合并
    }

    int ans=-1;
    for(int i=1;i<=n;++i)
        ans=max(ans,f[i][i+n-1]);

    cout<<ans;

    
    system("pause");
    return 0;
        
        

}

\(D\)题 [SCOI2005] 互不侵犯

#include<bits/stdc++.h>
using namespace std;
long long f[10][100][2010];

bool sta(int s1,int s2)
{
    if(((s1<<1)|(s1>>1))&s1)
        return 0;
    if(((s2<<1)|(s2>>1))&s2)
        return 0;
    if(((s1<<1)|s1|(s1>>1))&s2)
        return 0;
    return 1;
}
int get_num(int s)//计算s二进制中有多少个1
{
    int ret=0;
    while(s)
    {
//    	cout<<(s&1)<<" ";
        ret+=(s&1);//取二进制最后一位的1加入ret
        s>>=1;//s右移一位
    }
    return ret;
}

int main()
{
    int n,k;
    cin>>n>>k;

    f[0][0][0]=1;

	int maxn=1<<(n);
    for(int i=1;i<=n;++i)//枚举当前行i
    for(int s1=0;s1<maxn;++s1)//枚举本行状态s1
    for(int s2=0;s2<maxn;++s2)//枚举上一行状态s2
    {
    	if(sta(s1,s2)==0)
            continue;
	    for(int num=0;num<=k;++num)//枚举放了的棋子数
	    {
	//        cout<<s1<<"\n"; 
	        int num_s1=get_num(s1);
	//        cout<<num_s1<<" ";
	        if(num-num_s1>=0)//可以进行dp
	            f[i][num][s1]+=f[i-1][num-num_s1][s2];
	    }
    }

    long long ans=0;
    for(int i=0;i<maxn;++i)
        ans+=f[n][k][i];

    cout<<ans;
    
    system("pause");
    return 0;

}
posted @ 2025-02-10 21:17  SamXia  阅读(23)  评论(0)    收藏  举报