Give Candies 递推 欧拉降幂 c++字符串取余 快速幂

 

题目描述

There are N children in kindergarten. Miss Li bought them N candies。To make the process more interesting, Miss Li comes up with the rule: All the children line up according to their student number (1…N), and each time a child is invited, Miss Li randomly gives him some candies (at least one). The process goes on until there is no candy. Miss Li wants to know how many possible different distribution results are there. 

输入

The first line contains an integer T, the number of test case.
The next T lines, each contains an integer N.
1 ≤ T ≤ 100
1 ≤ N ≤ 10^100000

输出

For each test case output the number of possible results (mod 1000000007).

样例输入

复制样例数据

1
4

样例输出

8

题意:老师有n个糖果,然后挨着分给n个同学,至少分一个,问分的方法数有多少种%1e9+7

很轻松可得递推公式:f(n)=f(0)+f(1)+f(2)......f(n-1) 将f(0)看为1;

答案即为pow(2,-1)%mod

先给出一个十进制快速幂T了的代码。。。。1300毫秒。

#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <string>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
using namespace std;
ll a, mod=1e9+7;
const int maxx=1e6+100;
char s[maxx];
ll mpow ( ll a, ll b, ll mod ) 
{
    ll rt;
    for (rt=1;b;b>>=1)
    {
        if(b&1)
        {
            rt=rt*a;
            if(rt>mod) rt%=mod;
        }
        a=a*a;
        if(a>mod) a%=mod;
    }
    return rt;
}
ll kuaisumi(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) 
        {
            ans=ans*a;
            if(ans>mod) ans%=mod;
        }
        a=(a*a);
        if(a>mod) a%=mod;
        b>>=1;
    }
    return ans;
}
int main () 
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf ("%s",s);
        int len = strlen (s);
        reverse(s,s+len);
        //printf("%c\n",s[len-1]);
        ll base = 2;
        ll cur = 1;
        for (int i = 0; i < len; i++) {
            cur=cur*mpow(base,s[i]-'0',mod);
            if(cur>mod) cur%=mod;
            base=mpow(base,10,mod);
            if(base>mod) base%=mod;
        }
        ll x=kuaisumi(2,mod-2);
        cur=(cur*x)%mod;
        printf ("%lld\n", cur);
    }
}

这是一个能过的十进制快速幂

800mm

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int 
#define ll long long 
ll b,len,h,P,i,j;
const ll mod=1e9+7;
char c[100007];
ll kuaisumi(ll a)
{
    ll ans=1,s=a;
    while(len>=0)
	{
        ll cnt=c[len]-'0',cur=s;
        for(ri i=1;i<=cnt;i++)
        {
        	ans=(ans*s)%mod;
		}
		for(ri i=1;i<10;i++)
		{
			cur=(cur*s)%mod;
		}
		s=cur;
		ans%=mod;
		len--;
    }
    return ans;
}
ll niyuan(ll a,ll b)
{
	ll ans=1;
    while(b)
    {
        if(b&1) 
        {
            ans=ans*a;
            if(ans>mod) ans%=mod;
        }
        a=(a*a);
        if(a>mod) a%=mod;
        b>>=1;
    }
    return ans;
}
int main()
{
	int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf ("%s",c);
        len=strlen(c);
        len--;	
        ll x=niyuan(2,mod-2);
        ll ans=kuaisumi(2);
        printf ("%lld\n",(x*ans)%mod);
    }
	return 0;
}

 

 

给出欧拉降幂的公式 :

pow(a,b)%mod=pow(a,b%ϕ(a)) %mod       b>ϕ(a)   && gcd(a,b)==1

然后给出一个欧拉筛的代码,ϕ(x)代表小于x的数中与x互质的个数;

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include<string.h>     
#include<algorithm>
#define ll long long
#define hengheng main ()
using namespace std;
const int maxx=1e6+200;
int sushu[maxx];
bool biaoji[maxx];
ll i,j,m,n,k;
int cnt=0;
ll ola[maxx]; 
void olashai()
{
	memset(biaoji,true,sizeof(biaoji));
	for(i=2;i<maxx;i++)
	{
		if(biaoji[i]!=0)//  还未被标记 
		{	
			sushu[cnt]=i; 
			cnt++;
			ola[i]=i-1;
		 } 
		for(j=0;j<cnt&&sushu[j]*i<maxx;j++)  //用素数筛素数 
		{
			biaoji[sushu[j]*i]=0; // 标记出素数的倍数 
			if(i%sushu[j]==0)   //i是这个素数的倍数 
			{
				ola[sushu[j]*i]=ola[i]*sushu[j];
				break;  //用一个素数筛到即可,如用素数2筛了14就不需要用7筛14了  
			}
				else
				ola[sushu[j]*i]=ola[i]*(sushu[j]-1);
		}
	}
}
int hengheng
{
	olashai();
	ola[1]=1;
	for(i=2;i<=1000000;i++) 
	ola[i]+=ola[i-1];
	while(scanf("%d",&n)!=EOF)
	{
		if(n==0) break;
		printf("%lld\n",ola[n]);
	}
	
	return 0;
}

 

 

 

正解:

大数取余:就是一个模拟而已;

        ll len=strlen(s);
        ll ans = 0;//大数取余模板ll 
        for (int i = 0; i < len; ++i) 
        {
            ans = ans * 10 + (s[i] - '0');
            ans %= mod-1;
        }

#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <string>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
using namespace std;
ll a, mod=1e9+7;
const int maxx=1e6+100;
char s[maxx];
ll kuaisumi(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) 
        {
            ans=ans*a;
            if(ans>mod) ans%=mod;
        }
        a=(a*a);
        if(a>mod) a%=mod;
        b>>=1;
    }
    return ans;
}
int main () 
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf ("%s",s);
        ll len=strlen(s);
        ll ans = 0;//大数取余模板ll 
        for (int i = 0; i < len; ++i) 
        {
            ans = ans * 10 + (s[i] - '0');
            ans %= mod-1;
        }
        printf("%lld\n",kuaisumi(2,ans-1));
    }
}

 

 

以下是一个分糖果的 C++ 代码示例: ```cpp #include <iostream> using namespace std; int main() { int n, k; cin >> n >> k; // n 个孩子,k 颗糖果 int candies[n], sum = 0; for (int i = 0; i < n; i++) { cin >> candies[i]; // 每个孩子想要的糖果数 sum += candies[i]; } if (sum < k) { // 糖果不够分 cout << "No" << endl; return 0; } int avg = sum / n; // 平均每个孩子能拿到的糖果数 for (int i = 0; i < n; i++) { int give = min(avg, candies[i]); // 每个孩子最多只能拿到想要的糖果数 k -= give; candies[i] -= give; } while (k > 0) { // 如果还有剩余糖果,从拥有糖果最少的孩子开始发放 int min_candies = 1000000, min_index = -1; for (int i = 0; i < n; i++) { if (candies[i] < min_candies) { min_candies = candies[i]; min_index = i; } } candies[min_index]++; k--; } cout << "Yes" << endl; return 0; } ``` 这个程序首先读入 n 个孩子的想要糖果数和糖果总数 k,然后计算出每个孩子平均能拿到的糖果数。接下来,程序从每个孩子想要的糖果数和平均糖果数中取一个较小值,作为该孩子最终能拿到的糖果数,并从总糖果数 k 中减去这个数量。这样一轮下来,所有孩子都至少拿到了平均数的糖果。如果此时糖果还有剩余,程序会把剩余的糖果从拥有糖果最少的孩子开始发放,直到所有糖果都被发放完毕。最后,如果每个孩子都拿到了至少平均数的糖果,程序输出 Yes;否则输出 No。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值