zoukankan      html  css  js  c++  java
  • 7.25 鸽巢原理,中国剩余定理,欧拉函数

    A题:给你一个序列,长度为n。问是否存在一个连续的子序列和是m的倍数

    鸽巢原理,求出序列的前缀和数组,若pre[i]%m==pre[j]%m,则(pre[j]-pre[i])%m==0;

    B题:给出5个整数a,b,c,d,k。你要在[a,b]中找一个x,在[c,d]中找一个y,使得gcd(x,y)=k。请输出所有可能的组合数。
    注意(x=5, y=7) 和 (x=7, y=5)是一样的。所有数据a=c=1;

    gcd(x,y)=k,则gcd(x/k,y/k)=1,问题转化为求有多少组互素的x,y;

    我们将b/=k;d/=k;枚举从1到b每一个x,求在(1,d)区间有多少与x互素的数;用容斥原理来求,与x互素的数的个数等于(d-与x不互素的元素的个数)=(d-与x有相同因子的元素的个数);

    故将x质因数分解,套用容斥模板即可;

    这里注意,因为(5,7)(7,5)是一样的,所以我们枚举1到min(b,d)的x,将x 质因数分解,然后求区间[x,d]与x互素的元素的个数(为什么这里是[x,d]不是[x+1,d]是因为1与1互素,如果要写[x+1,d]最后让ans++即可;)(为什么是[x,d]而不是[1,d],是因为避免重复,例如x=2,你找到了3,5,7;那么在找3,5,7的时候,你又把2算了一遍,所以我们总是从大于等于x的区间找;

    这里特别注意区间和问题,求[l,r]=solve(r)-solve(l-1);(不要把 l 这个点给剪掉了)

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 #define LL long long
     7 const int maxn=1e6;
     8 int cnt,p=0;
     9 bool isprime[maxn];
    10 int prime[maxn];
    11 int prime_n[maxn];
    12 void init()
    13 {
    14     LL i,j;
    15     for(i=2;i<maxn;i++)
    16     {
    17         if(!isprime[i])
    18         {
    19             prime[p++]=i;
    20             for(j=i*i;j<maxn;j+=i)
    21                 isprime[j]=true;
    22         }
    23     }
    24 }
    25 void only(LL n)
    26 {
    27     LL i,j;
    28     cnt=0;
    29     for(i=0;i<p&&prime[i]*prime[i]<=n;i++)
    30     {
    31        if(n%prime[i]==0)
    32        {
    33            prime_n[cnt++]=prime[i];
    34            while(n%prime[i]==0)
    35            {
    36                n/=prime[i];
    37            }
    38        }
    39     }
    40     if(n>1)prime_n[cnt++]=n;
    41 }
    42 LL solve(LL r)
    43 {
    44     LL i,j,ans=0;
    45     for(i=1;i<(1<<cnt);i++)
    46     {
    47         LL tnt=0,mult=1;
    48         for(j=0;j<cnt;j++)
    49         {
    50             if((i>>j)&1)
    51             {
    52                 mult*=prime_n[j];
    53                 tnt++;
    54             }
    55         }
    56         if(tnt&1)ans+=r/mult;
    57         else ans-=r/mult;
    58     }
    59     return r-ans;
    60 }
    61 int main()
    62 {
    63     init();
    64     int t;
    65     cin>>t;
    66     int T=1;
    67     while(t--)
    68     {
    69         int a,b,c,d,k;
    70         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    71         if(k==0||k>b||k>d)printf("0
    ");
    72         else
    73         {
    74           b/=k;
    75           d/=k;
    76           int n=min(b,d);
    77           int m=max(b,d);
    78           LL ans=0;
    79           int res,i;
    80           for(i=1;i<=n;i++)
    81          {
    82              only(i);
    83              ans+=solve(m)-solve(i-1);
    84          }
    85          printf("Case %d: %lld
    ",T,ans);
    86         }
    87         T++;
    88     }
    89     return 0;
    90 }
    View Code

    C题:欧拉树

    发现树的两边是完全对称的,只看左边,递归求解,最简分式上下互素,对于n,存在以n为分母的个数为n的欧拉数

    D题:HHM非常喜欢读书,已知他每天看a1页,那么最后还有b1页没有看;看a2页,还有b2页没有看....看ak页还有bk页没有看。请问这本书有多少页

    典型的中国剩余算法问题

    即xmod a1=b1;

    xmod a2=b2;

    xmod a3=b3;

    .......

    因为题目没有说a1,a2,..an互素,所以用不互素的中国剩余定理模板即可。

    求出来的数即为最小满足条件的x

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long LL;
     5 typedef pair<LL, LL> PLL;
     6 LL a[100000], b[100000], m[100000];
     7 LL gcd(LL a, LL b){
     8     return b ? gcd(b, a%b) : a;
     9 }
    10 void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    11     if (!b) {d = a, x = 1, y = 0;}
    12     else{
    13         ex_gcd(b, a % b, y, x, d);
    14         y -= x * (a / b);
    15     }
    16 }
    17 LL inv(LL t, LL p){//如果不存在,返回-1
    18     LL d, x, y;
    19     ex_gcd(t, p, x, y, d);
    20     return d == 1 ? (x % p + p) % p : -1;
    21 }
    22 PLL linear(LL A[], LL B[], LL M[], int n) {//求解A[i]x = B[i] (mod M[i]),总共n个线性方程组
    23     LL x = 0, m = 1;
    24     for(int i = 0; i < n; i ++) {
    25         LL a = A[i] * m, b = B[i] - A[i]*x, d = gcd(M[i], a);
    26         if(b % d != 0)  return PLL(0, -1);//答案,不存在,返回-1
    27         LL t = b/d * inv(a/d, M[i]/d)%(M[i]/d);
    28         x = x + m*t;
    29         m *= M[i]/d;
    30     }
    31     x = (x % m + m ) % m;
    32     return PLL(x, m);//返回的x就是答案,m是最后的lcm值
    33 }
    34 int main(){
    35     int n;
    36     while(scanf("%d", &n) != EOF){
    37         for(int i = 0; i < n; i ++){
    38             a[i] = 1;
    39             scanf("%d%d", &m[i], &b[i]);
    40         }
    41         PLL ans = linear(a, b, m, n);
    42         if(ans.second == -1) printf("-1
    ");
    43         else printf("%I64d
    ", ans.first);
    44     }
    45 }
    View Code
  • 相关阅读:
    设计模式学习每日一记(1.简单工厂模式)
    poj1068
    设计模式学习每日一记(2.外观模式)
    qooxdoo一句话备忘录[不断更新]
    设计模式学习每日一记(4.抽象工厂)
    C# 各种数据类型的最大值和最小值常数
    ASP.NET中实现二级或多级域名(修改UrlRewrite)
    网站中定时发送邮件
    重提URL Rewrite(1):IIS与ASP.NET
    Server Application Unavailable 的解决方法
  • 原文地址:https://www.cnblogs.com/raincle/p/9367777.html
Copyright © 2011-2022 走看看