郑轻新生热身赛 部分题解

1.欧拉函数

int euler(int n)
{
    int m=int(sqrt(n+0.5));
    int ans=n;
    for(int i=2;i<=n/i;i++)
    {
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0) n/=i;
        }
    }
    if(n>1)
    ans=ans/n*(n-1);
    return ans;
}

2.容斥原理


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+100;
const int mod=1e9+7;
typedef pair<int,int> PII; 
#define x first
#define y second
#define pb push_back
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
vector<int> ans;
ll n,n1,an,len;
int vis[N];

void dfs(int u)
{
    if(u==len)
    {
        int cnt=0;
        ll x=1;
        for(int i=0;i<len;i++)
        {
            if(vis[i])
            x*=ans[i];
            
            cnt+=vis[i];
        }
        if(x==1) return;
        if(cnt&1)
        an+=n1/x;
        else
        an-=n1/x;

        return;
    }
    for(int i=0;i<=1;i++)
    {
        vis[u]=i;
        dfs(u+1);
        vis[u]=0;
    }
    
 

}


int main()
{
    cin>>n;
    n1=n;
    for(int i=2;i<=n/i;i++)
    {
        if(n%i==0)
        {
            ans.pb(i);
            while(n%i==0)
              n/=i;         
        }
    }
    if(n>1)
    ans.pb(n);
    len=ans.size();

    dfs(0);
    cout<<n1-an<<endl;
    





    return 0;
}


 

 

 状压+DFS(判断是否合法)

DFS暴力直接T

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+100;
const int mod=1e9+7;
typedef pair<int,int> PII; 
#define x first
#define y second
#define INF 0x3f3f3f3f
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int x[]={1,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,5};  //输入简化
int y[]={1,2,4,5,2,3,4,2,3,4,2,3,4,1,2,4,5};
int dist[20][20],st[20][20],g[20][20];
vector<PII> Q;
int sum,cnt,ans;// cnt记录每种状态里有多少格子被占领,sum为dfs实际被占领的格子,ans为掷筛子的次数
void dfs(int x,int y)
{
     st[x][y]=1;       //写到外面,
    for(int i=0;i<4;i++)
    {
        int xx=x+dx[i],yy=y+dy[i];
        if(xx<1||xx>5||yy<1||yy>5) continue;
        
        if(dist[xx][yy]&&!st[xx][yy])
        {     
            //st[x][y]=1;  
            sum++;
            dfs(xx,yy);
        }
    }


}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(g,0,sizeof g);  //记得初始化
        for(int i=0;i<17;i++)
        {
            cin>>g[x[i]][y[i]];
            Q.push_back({x[i],y[i]});     
        }
        int n,res=0;
        cin>>n;
        
        for(int i=0;i<(1<<17);i++)
        {
            memset(dist,0,sizeof dist);//记得初始化
            memset(st,0,sizeof st);//记得初始化
            ans=cnt=sum=0;          //每次状态也要初始化为0
            for(int j=0;j<17;j++)
            {
                if(i>>j&1)
                {
                    cnt++;
                    dist[Q[j].x][Q[j].y]=1;
                    ans+=(g[Q[j].x][Q[j].y]+5)/6;   //比如 13 则正确返回 3
                                                    //不如分类讨论是g能否整除6
                }
            }
            if(!dist[5][1]||ans>n) continue;
            
            sum=1;   //dist[5][1]=1
            dfs(5,1);
            if(sum==cnt)
            res=max(res,cnt);


        }
        cout<<res<<endl;
    }

    return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值