AGC047 A - Integer Product(思维)

tech2024-07-14  57

题意:

给定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)