uva12716 GCD XOR(打表找规律+筛法)

题意:输入整数(1=<n<=30000000),有多少对整数(a,b)满足:1=<b=<a=<n,且gcd(a,b)=a^b。例如n=7时,有4对:(3,2),(5,4),(6,4),(7,6)

解题思路:

看到题目之后一直在找最大公约数和异或之间的关系,但找了半天没有发现。于是果断打表发现如下规律

满足gcd(a,b)=a^b的数有如下规律,要么就是a=b-1,要么就是有前面已求得的满足条件的乘上一定的倍数得到如下:

根据上述规律,我们便可以求的所有的可能性,上面只打印了一部分,整个程序2秒左右完成预处理

所以对于每次符合条件的(a,a-1),我们运用类似筛法的方法去叠加即可时间复杂度O(nlogn)

代码:

#include <cstdio>
#include <cstring>
#define MAXN 30000001
using namespace std;
int d[MAXN];
int main(){
    int maxn=30000000;
    for(int i=3;i<=maxn;i++)
    {
        if(1==(i^(i-1))){
            d[i]++;
            int j,k;
            for(j=i<<1,k=2;j<=MAXN;j+=i,k++){
                if(k==(j^(j-k)))
                    d[j]++;
            }
        }
    }
    for(int i=3;i<=MAXN;i++)
        d[i]+=d[i-1];
    int T;
    scanf("%d",&T);
    int n;
    for(int t=1;t<=T;t++){
        scanf("%d",&n);
        printf("Case %d: %d\n",t,d[n]);
    }
    return 0;
}

收获:

1、数学上许多问题都可以通过打表寻找规律;

2、对于数据很大的情况,一个很小的细节就可能在超时,所以当数据很大时,每一步尽量都做到最优

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-28 14:23:28

uva12716 GCD XOR(打表找规律+筛法)的相关文章

UVA-12716 - GCD XOR

[思路]a^b = c等价于a^c = b  所以枚举a和c,而a和c全部枚举肯定TLE,所以高效算法:通过c是a的约数这个关系来枚举会减小循环,必须要将c放在循环外面,因为c的情况比较少.其实本题就是要求:c=a-b(规律),c=a^b 以下是高神的AC代码,很好很强大: #include <cstdio> #include <iostream> #include <cmath> #include <string> using namespace std;

hdu 2147 kiki&#39;s game(DP(SG)打表找规律)

题意: n*m的棋盘,一枚硬币右上角,每人每次可将硬币移向三个方向之一(一格单位):左边,下边,左下边. 无法移动硬币的人负. 给出n和m,问,先手胜还是后手胜. 数据范围: n, m (0<n,m<=2000) 思路: dp[i][j]=0,说明从(i,j)这个点到时左下角先手败.dp[i][j]=1则先手胜. 然后记忆搜.但是记忆搜会超时. 搜完把整张表打出来,发现规律了,,,,然后,,,代码剩几行了. 代码: ///打表观察 /* int f[2005][2005]; int go(in

【ZOJ】3785 What day is that day? ——浅谈KMP应用之ACM竞赛中的暴力打表找规律

首先声明一下,这里的规律指的是循环,即找到最小循环周期.这么一说大家心里肯定有数了吧,“不就是next数组性质的应用嘛”. 先来看一道题 ZOJ 3785 What day is that day? Time Limit: 2 Seconds      Memory Limit: 65536 KB It's Saturday today, what day is it after 11 + 22 + 33 + ... + NN days? Input There are multiple tes

hdu_5894_hannnnah_j’s Biological Test(打表找规律)

题目链接:hdu_5894_hannnnah_j’s Biological Test 题意: 有n个不同的位置围成一个圈,现在要安排m个人坐,每个人至少的间隔为k,问有多少种安排 题解: 先打表找规律,最后发现答案为n*C(n-m*k-1,n-m*k-m)/m 然后这里求组合要预处理一下,逆元也预处理一下 最后还要特判m为1的情况 1 #include<cstdio> 2 typedef long long ll; 3 const int P=1e9+7; 4 5 const int maxn

【NOIP 模拟赛】中值滤波 打表找规律

对于这样看起来不像什么算法也没什么知识点的题,一脸懵逼的话不是手推规律就是打表找规律......... 当然还有一些超出你能力之外的数学题...... #include <cstdio> const int N=500010; int n,ans,A[N]; inline int Max(int x,int y){ return x>y?x:y; } int main(){ scanf("%d",&n); int last,now,P=0; for(int i

HDU2149-Good Luck in CET-4 Everybody!(博弈,打表找规律)

Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4762    Accepted Submission(s): 3058 Problem Description 大学英语四级考试就要来临了,你是不是在紧张的复习?或许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和C

HDU 4588 Count The Carries 数位DP || 打表找规律

2013年南京邀请赛的铜牌题...做的很是伤心,另外有两个不太好想到的地方....a 可以等于零,另外a到b的累加和比较大,大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数,然后统一进位. 设最低位为1,次低位为2,依次类推,ans[]表示这一位上有多少个1,那么有 sum += ans[i]/2,ans[i+1] += ans[i]/2; sum即为答案. 好了,现在问题转化成怎么求ans[]了. 打表查规律比较神奇,上图不说话. 打表的代码 #include <algo

hdu_5793_A Boring Question(打表找规律)

题目链接:hdu_5793_A Boring Question 题意: 自己看吧,说不清楚了. 题解: 打表找规律 1 #include<cstdio> 2 typedef long long ll; 3 4 const int mod=1e9+7; 5 ll pow(ll a,ll b) 6 { 7 ll an=1; 8 while(b){ 9 if(b&1)an=(an*a)%mod; 10 b>>=1,a=(a*a)%mod; 11 } 12 return an; 1

HDU 3032 (SG打表找规律)

题意: 有n堆石子,alice先取,每次可以选择拿走一堆石子中的1~x(该堆石子总数) ,也可以选择将这堆石子分成任意的两堆.alice与bob轮流取,取走最后一个石子的人胜利. 思路: 因为数的范围比较大,所以最好通过SG打表的结果找出规律在解. sg(4k+1)=4k+1;sg(4k+2)=4k+2;sg(4k+3)=4k+4; sg(4k)=4k-1; 1 2 4 3 5 6 8 7 Sample Input232 2 323 3 Sample OutputAliceBob SG打表找规律