VOJ - For the Honest Election (递归/筛法)

For the Honest Election

题目链接:L - For the Honest Election Gym - 100247L

题意

有n个人要投票选市长,P想当市长,所以他要找一些支持者给他投票,他可以把一群人分成若干人数相等的小组,对每个小组还可以执行类似的操作,投票规则是每个组分成的小组中有过半组投支持P这个组才支持P,问P通过适当的分组后让自己被选上市长需要的最少支持者

思路

第一种,利用递归的思想,将大的人数,不断划分成小的人数,因为这个很明显是需要利用乘法原理的,比如有十五个人,3 * 5和5 * 3结果是一样的,所以现在只需,不断将数据划分成各个质数即可。每个质数的对应数应该是n/2+1

第二种,则将第一种思想用筛法来进行实现,哎,这样需要考虑的情况过多,因为2非常特殊,每次在2的倍数,不是由2所对应的质数所组合而成,而是有4和8所组合而成,比较复杂,需特判。说明我对于2的特殊性,没有考虑周全。

代码

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const int MAXN = (int)1e6+7;
const int INF = (int)0x3f3f3f3f;

map<ll,ll> dp;
ll solve(ll N){
    if (dp[N]!=0) return dp[N];
    ll ans = N/2+1;
    for (ll i = 2;i*i <= N;i ++){
        if (N%i == 0) {
            ans = min(ans,solve(N/i)*solve(i));
        }
    }
    return dp[N] = ans;
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int N;
    dp[1] = 1;
    cin >> N;
    cout << solve(N) << endl;
}
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(ll i = (ll)j;i <= (ll)k;i ++)
#define per(i,j,k) for(ll i = (ll)j;i >= (ll)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const ll MAXN = (ll)3e6+7;
const ll INF = (ll)0x3f3f3f3f;

ll isNoPrim[MAXN];

ll N;

int main()
{
    scanf("%lld",&N);

    isNoPrim[1] = 1;
    ll sr = (ll)sqrt(N);
    rep(i,2,sr+1){
        if (isNoPrim[i] != 1){
            isNoPrim[i] = (i+1)/2;
            if (i == 2) isNoPrim[i] = 2;
            for (ll j = 2;j*i <= sr+1;j ++){
                isNoPrim[i*j] = 1;
            }
        }
    }

    ll tmp = 0;
    ll ans = 1;
    while (N % 2 == 0){
        tmp ++;
        N /= 2;
    }
    while (tmp >= 7 ) tmp -= 3,ans *= 5;
    if (tmp == 1) ans *= 2;
    if (tmp == 2) ans *= 3;
    if (tmp == 3) ans *= 5;
    if (tmp == 4) ans *= 3*3;
    if (tmp == 5) ans *= 3*5;
    if (tmp == 6) ans *= 5*5;

    rep(i,2,sr+1){
        if (isNoPrim[i] > 1){
            while(N%i==0) {
                ans *= (ll)isNoPrim[i];
                N /= i;
            }
        }
    }
    if (N > 1) ans *= (N+1)/2;
    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_40513946/article/details/81173040