zoukankan      html  css  js  c++  java
  • 方程的解_NOI导刊2010提高

    方程的解

    给定x,求(a_1+a_2+...+a_k=x^x mod 1000)的正整数解解的组数,对于100%的数据,k≤100,x≤2^31-1。

    显然x是可以快速幂得到答案的,而该问题显然是组合计数的问题,换一种解释即(b=x^x)个相同的数能怎样放进k个有标号盒子。

    思路一

    而无法解决无标号放入有标号。于是逆向思维,把有标号盒子放入无标号(b)个数,有标号盒子可以重复放,无标号$b数个只能被放一次,因为是正整数的缘故,所以盒子必须保证放过,故事先构造放满,再套用可重组合公式,有

    [C_{k+b-k-1}^{k-1}=C_{b-1}^{k-1} ]

    思路二

    注意到组合问题很难解决,故考虑排列,而这又是划分问题,故考虑全排列划分模型,即有k-1个0与b个1进行全排列,0去划分1,但是注意到要的是正整数解,于是0之间必须有1,于是事先填好1,有

    [frac{(k-1+b-k)!}{(k-1)!(b-k)!}=C_{b-1}^{k-1} ]

    得到公式后根据所得条件按质因数分解型的阶乘高精处理即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    #define yyb 1000
    using namespace std;
    struct lll{
        short num[5000];
        il lll(){num[0]=1;}
        il void clear(){memset(num,0,sizeof(num)),num[0]|=true;}
        template<class free>
        il void operator=(free x){
            num[0]=0;
            while(x)num[++num[0]]=x%10,x/=10;
        }
        il lll operator*(lll x){
            lll y;y.clear();
            for(ri int i(1),j,k;i<=num[0];++i){
                k=0;
                for(j=1;j<=x.num[0];++j)
                    y.num[i+j-1]+=num[i]*x.num[j]+k,
                        k=y.num[i+j-1]/10,y.num[i+j-1]%=10;
                y.num[i+x.num[0]]+=k;
            }y.num[0]=num[0]+x.num[0];
            while(!(y.num[y.num[0]])&&y.num[0]>1)--y.num[0];
            return y;
        }template<class free>
        il lll operator^(free y){
            lll x(*this),ans;ans=1;
            while(y){
                if(y&1)ans=ans*x;
                x=x*x,y>>=1;
            }return ans;
        }
        il void print(){
            for(ri int i(num[0]);i;--i)putchar(num[i]+48);
        }
    };
    lll xdk[250];
    bool check[1100];
    int prime[250],sp[250],tot;
    il int pow(int,int);
    il void c(int,int),sieve(int);
    int main(){
        int k,x;
        scanf("%d%d",&k,&x),x=pow(x%yyb,x);
        sieve(x-1),c(x-1,k-1);
        return 0;
    }
    il void sieve(int n){
        for(ri int i(2),j;i<=n;++i){
            if(!check[i])prime[++tot]=i,xdk[tot]=i;
            for(j=1;j<=tot&&prime[j]*i<=n;++j){
                check[i*prime[j]]|=true;
                if(!(i%prime[j]))break;
            }
        }
    }
    il void c(int n,int r){
        if(n<r)return (void)(puts("0"));
        int i,j;lll ans;ans=1;
        for(i=1;i<=tot;++i)
            for(j=n;j;j/=prime[i])sp[i]+=j/prime[i];
        for(i=1;i<=tot;++i)
            for(j=r;j;j/=prime[i])sp[i]-=j/prime[i];
        for(i=1;i<=tot;++i)
            for(j=n-r;j;j/=prime[i])sp[i]-=j/prime[i];
        for(i=1;i<=tot;++i)ans=ans*(xdk[i]^sp[i]);ans.print();
    }
    il int pow(int x,int y){
        int ans(1);while(y){
            if(y&1)ans=ans*x%yyb;
            x=x*x%yyb;y>>=1;
        }return ans;
    }
    
  • 相关阅读:
    读写二进制c# 二进制读写
    重构风险程序员一定要遵守的规则
    文件区域使用fcntl锁定文件,并且测试
    数据清空js清空div里的数据问题
    模板缓存ThinkPHP中的模板引擎和视图层
    描述null11121 Base 2
    操作系统请求操作系统 算法
    工程项目eclipse项目名前出现红色感叹号,小红叉解决
    程序链接关于静态链接,动态链接,共享库,ABI的一些记录(os学习)
    NMAKE命令行编译
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10781593.html
Copyright © 2011-2022 走看看