AGC047 A - Integer Product(思维)

题意:

给定n个最多9位小数的实数序列a,问有多少个有序数对<i,j>,满足a(i)*a(j)是整数

数据范围:n<=2e5,0<a(i)<1e4

解法:
将每个数乘上1e9变成整数,
那么我们要找的是乘积是1e18的倍数的数对.

分解出每个数质因子25的个数,
那么可以计算出两个数相乘之后末尾有多少个0,
如果>=18则满足条件

然后每个数可以变为形如(cnt2,cnt5)的数对,
假设(a,b)(c,d)相乘,那么0的个数为min(a+c,b+d)
我们要找的就是min(a+c,b+d)>=18的数对个数
因为n最大2e5,枚举数对肯定不行.

考虑到每个数对中2的个数最多log(1e4*1e9)<45,
那么直接开二维桶g[x][y]表示数对为(x,y)的数量,
枚举乘积的结果数对即可,复杂度O(70*70*45*45)<1e7
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=2e5+5;
int num[45][45];
int a[maxm];
int n;
signed main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++){//用字符串读,避免误差
        string s;cin>>s;
        int num=0;
        int cnt=-1;
        for(auto x:s){
            if(isdigit(x)){
                num=num*10+x-'0';
                if(cnt>0)cnt--;
            }else{//小数点
                cnt=9;
            }
        }
        if(cnt==-1)cnt=9;//如果没有小数点
        while(cnt-->0)num=num*10;
        a[i]=num;
    }
    for(int i=1;i<=n;i++){
        int c2=0,c5=0;
        while(a[i]%2==0){
            c2++;
            a[i]/=2;
        }
        while(a[i]%5==0){
            c5++;
            a[i]/=5;
        }
        num[c2][c5]++;
    }
    int ans=0;
    for(int i=18;i<=90;i++){
        for(int j=18;j<=90;j++){
            //枚举结果数对(i,j)
            for(int x=0;x<45&&x<=i;x++){
                for(int y=0;y<45&&y<=j;y++){
                    int xx=i-x,yy=j-y;
                    if(xx<0||xx>=45||yy<0||yy>=45)continue;
                    if(xx==x&&yy==y){//相等的情况特判一下,不能匹配自己
                        ans+=num[x][y]*(num[x][y]-1);
                    }else{
                        ans+=num[x][y]*num[xx][yy];
                    }
                }
            }
        }
    }
    ans/=2;//无序转有序
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值