C - Yet Another Counting Problem(打表+周期)
题意: 给出a,b,q,如果x%a%b!=x%b%a那么x为特殊数,在q次询问的时候给出区间[l,r],问在此区间内特殊数的个数是多少。
题解: 在1~a*b区间为一个周期,然后每个周期个数都相同,所以用前缀和统计一个周期然后计算即可
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std ;
typedef long long ll ;
const int N = 510 ;
ll ans[N] ;
ll f[40005] ;
int main(){
int t ; scanf("%d",&t) ;
while(t--){
int a,b,q ;
scanf("%d%d%d",&a,&b,&q) ;
int T = a*b ;
for(int i=1 ; i<=a*b ; ++i) f[i+1]=f[i]+(i%a%b!=i%b%a) ;
for(int i=0 ; i<q ; ++i){
ll l,r ;
scanf("%lld%lld",&l,&r) ;
++r ;
ll n=r/T*f[T]+f[r%T] ;
ll m=l/T*f[T]+f[l%T] ;
ans[i] = n-m ;
}
for(int i=0 ; i<q-1 ; ++i) printf("%lld ",ans[i]) ;
printf("%lld\n",ans[q-1]) ;
}
return 0 ;
}
D - Multiple Testcases
题意: 给出一个长度为n的数组m[] 还有一个长度为k的数组c[],要求构造最少的数组,并且满足大于等于i的数不超过c[i]个。
题解: 先确定最少的数组,将m降序排列,m[i]能分成的最少数组为:大于等于m[i]的数目x / c[m[i]] ,然后不断更新ans,最后从大到小依次放入ans个数组中即可。
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std ;
typedef long long ll ;
const int N = 2e5+10 ;
int m[N] ,c[N] ;
vector<int> v[N] ;
bool cmp(int a,int b){
return a>b ;
}
int main(){
int n,k ; scanf("%d%d",&n,&k) ;
for(int i=1 ; i<=n ; ++i) scanf("%d",&m[i]) ;
for(int i=1 ; i<=k ; ++i) scanf("%d",&c[i]) ;
sort(m+1,m+1+n,cmp) ;
int ans = 0 ;
for(int i=1 ; i<=n ; ++i)
ans = max(ans,(int)ceil(1.0*i/c[m[i]])) ;
printf("%d\n",ans) ;
for(int i=1 ; i<=n ; ++i)
v[i%ans].push_back(m[i]) ;
for(int i=0 ; i<ans ; ++i){
printf ("%d ",v[i].size()) ;
for(int j=0 ; j<v[i].size() ; ++j)
printf ("%d ",v[i][j]) ;
printf ("\n") ;
}
return 0 ;
}