1. 程式人生 > >【SDOI2014】【BZOJ3529】數表

【SDOI2014】【BZOJ3529】數表

pre rac bzoj3 comment sdoi code sdn 給定 content

Description

有一張N×m的數表,其第i行第j列(1 < =i < =禮。1 < =j < =m)的數值為

能同一時候整除i和j的全部自然數之和。給定a,計算數表中不大於a的數之和。

Input

輸入包括多組數據。
輸入的第一行一個整數Q表示測試點內的數據組數,接下來Q行,每行三個整數n,m,a(|a| < =10^9)描寫敘述一組數據。

Output

對每組數據,輸出一行一個整數。表示答案模2^31的值。

Sample Input

2

4 4 3

10 10 5

Sample Output

20

148

HINT

1 < =N.m < =10^5 。 1 < =Q < =2×10^4

Source

Round 1 Day 1

在反演上的處理和DzyLovesMath1是相似的屬於同一類題目
問題在於詢問有10^4個所以要BIT維護一下前綴和
推公式過程懶得放了…貼個Po姐課件的圖吧
技術分享
技術分享
(從未見過如此喪病的反演..反演還要加數據結構T_T

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100010 #define lowbit(x) (x&(-x)) #define LL long long #define MAXINT (0x7fffffff) #define GET (ch>=‘0‘&&ch<=‘9‘) using namespace std; int T,maxn; int c[MAXN]; bool not_prime[MAXN]; int prime[MAXN],mu[MAXN]={0,1},top; int ans[MAXN]; struct Query { int n,m,a,id; bool operator <(const Query& t)const {return
a<t.a;} }q[MAXN]; struct num { int a,b; bool operator <(const num& x)const {return a==x.a?b<x.b:a<x.a;} }f[MAXN]; void init() { for (int i=2;i<=maxn;i++) { if (!not_prime[i]) prime[++top]=i,mu[i]=-1; for (int j=1;j<=top&&i*prime[j]<=maxn;j++) { not_prime[i*prime[j]]=1;mu[i*prime[j]]=-mu[i]; if (i%prime[j]==0) {mu[i*prime[j]]=0;break;} } } for (int i=1;i<=maxn;i++) { for (int j=i;j<=maxn;j+=i) f[j].a+=i; f[i].b=i; } } void add(int x,int delta) {for (int i=x;i<=maxn;i+=lowbit(i)) c[i]+=delta;} int query(int x) { int ret=0; for (int i=x;i;i-=lowbit(i)) ret+=c[i]; return ret; } void in(int &x) { char ch=getchar();x=0;int flag=1; while (!GET) flag=(ch==‘-‘)?

-1:1,ch=getchar(); while (GET) x=x*10+ch-‘0‘,ch=getchar();x*=flag; } void calc(int x) { int id=q[x].id,n=q[x].n,m=q[x].m,last=0,t=min(n,m); for (int i=1;i<=t;i=last+1) { last=min(n/(n/i),m/(m/i)); ans[id]+=(n/i)*(m/i)*(query(last)-query(i-1)); } } int main() { in(T);int now=0; for (int i=1;i<=T;i++) in(q[i].n),in(q[i].m),in(q[i].a),q[i].id=i,maxn=max(maxn,max(q[i].n,q[i].m)); init();sort(q+1,q+T+1);sort(f+1,f+maxn+1); for (int i=1;i<=T;i++) { while (now+1<=maxn&&f[now+1].a<=q[i].a) { now++; for (int j=f[now].b;j<=maxn;j+=f[now].b) add(j,f[now].a*mu[j/f[now].b]); } calc(i); } for (int i=1;i<=T;i++) printf("%d\n",ans[i]&MAXINT); }

【SDOI2014】【BZOJ3529】數表