倒计时59天

(来源:b站左程云up  099)

一:求逆元:

1)要保证a可以整除b      2)要保证mod的是一个质数        3)b和mod互质

题目2)3)一般都满足,主要是1)

方法:如求1.(10/5)%mod   mod=3

     5的逆元其实就等于(5的mod-2次方)%mod=5%3=2;然后用10%mod=1,结果就等于(分母的逆元乘以分子mod后的值)%mod,即(2*1)%3=2!

                  2.(18/6)%mod   mod=5

     先求6的逆元,就是6的3次方再mod,如果mod太大用快速幂,之后结果就为1;18%5=3;3*1=3!

求1-n的逆元,1的话易知就是1,然后就接着用公式:

a[i]=(int)(mod-a[mod%i] * (mod/i)%mod)

求阶乘的逆元:

//第一步,求1-n阶乘的mod:

//1!%mod=1;然后用乘法同余:

//2!%mod=(1!%mod)*(2%mod)%mod    ;  3!%mod=(2!%mod)*(3%mod)%mod........

//把他们都存在一个数组里面,假设为b[N];

b[1]=1;
for(int i=2;i<=n;i++)
{
    b[i]=(i%mod)*(b[i-1]%mod)%mod;
}

第二步,可以直接套公式但比较慢:

快速幂:

int pow(int a,int b)
{
   int result=1;
   while(b)
  {
      if(b&1)
      {
          result=result*a%mod;
          b/=2;
          a=a*a%mod;
      }
      else
      {
          b/=2;
          a=a*a%mod;
      }
   }
return result;
}
//ps:0的逆元为1,因为0!=1;

//所以就是:c[0]=1;

c[0]=1;
for(int i=1;i<=n;i++)
{
   c[i]=pow(b[i],mod-2);
}

优化后:

所以由上面我们求Cnm,n! / ((n-m)!*m!)

而n!%mod 求出来了:b[n]

(n-m)!的逆元:c[n-m],m!的逆元:c[m]


int answer(int n,int m)
{
    int ans=b[n];
    ans=(ans*c[m])%mod;
    ans=(ans*c[n-m])%mod;
    return ans;
}

二:容斥原理:

相当于:a U b U c  的话:

就等于:a+b+c-a∩b-b∩c-a∩c+a∩b∩c

而如果aUbUcUdUe:

倒计时59天_第1张图片

倒计时59天_第2张图片

dp[i]表示最大公约数为i的子序列个数

倒计时59天_第3张图片

int DP()
{
    for(int i=n;i>=1;i--)
    {
        int cn=0;
        for(int j=i;j<=n;j+=i)
        {
            cn=(cn+d[j])%mod;
        }
        dp[i]=(pow[cn]-1+mod)%mod;
        for(int j=2*i;j<=n;j+=i)
        {
            dp[i]=(dp[i]-dp[j]+mod)%mod;//减法求余加mod
        }
    }
    return dp[1];
}


//2的0-n次方mod后的值
pow[0]=1;
for(int i=1;i<=n;i++)
{
   pow[i]=(pow[i-1]*2)%mod;
}

//d[i]:i出现的次数

for(int i=0;i>r;
    d[r]++;
}

你可能感兴趣的:(算法,c++)