A:判断一个数是否有大于1的奇因子。奇数直接yes,偶数判断一下是不是2的幂
while(t--) {
ll n;
cin >> n;
if(n%2==0)
{
while(!(n&1))
{
n/=2;
}
if(n == 1)
cout << "NO" << endl;
else cout << "YES" << endl;
}
else
cout << "YES" << endl;
} B:判断一个数n能不能用2020和2021表示。分别记录n除以2020和mod2020的值,比较大小。
while(t--) {
int n;cin >> n;
int tmp=n/2020,temp=n%2020;
if(temp<=tmp) cout << "YES" << endl;
else cout <<"NO"<< endl;
} C:给出男生、女生的总个数 a,b 和配对的组数 k。其中(x,y) 为一对,x表示男生编号,y表示女生编号。询问找出 2 个组且其中的男生女生不重复的挑选方法数。
思路1:统计男女生每个编号出现的次数cnta,cntb,当我们选择一对后,剩下还能选择就是k-(cnta-1)-(cntb-1)-1,cnta-1代表除了当前这一对男生可与其它女生配对的数量,cntb-1同理,最后再减一是减去我们最开始选择的那一对,剩下差值就为我们还能选择的对数。
while(t--) {
int aa,bb,k; cin >> aa >> bb >> k;
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
for(int i=1;i<=k;i++)
{
cin >> a[i];
vis1[a[i]]++;
}
for(int i=1;i<=k;i++)
{
cin >> b[i];
vis2[b[i]]++;
}
ll ans=0;
for(int i=1;i<=k;i++)
{
ll cnt1=vis1[a[i]]-1,cnt2=vis2[b[i]]-1;
ans+=k-cnt1-cnt2-1;
}
cout << ans / 2 << endl;
} 思路2:所有情况减去重复的情况。(long long)
while (T--) {
cin >> a >> b >> k;
for (int i = 0; i <= a; i++)A[i] = 0;
for (int i = 0; i <= b; i++)B[i] = 0;
for(int i = 1; i <= k; i++) {
int x;
cin >> x;
A[x]++;
}
for(int i = 1; i <= k; i++) {
int x;
cin >> x;
B[x]++;
}
ll ans = 1ll * k * (k - 1) / 2ll;
for(int i = 1; i <= a; i++) {
ans -= 1ll * A[i] * (A[i] - 1ll) / 2ll;
}
for(int i = 1; i <= b; i++) {
ans -= 1ll * B[i] * (B[i] - 1ll) / 2ll;
}
cout << ans << endl;
} D:删除内存和至少为m的应用,问最少将失去多少方便点。方便点要么为1要么为2,将每个应用按照方便点分类再排序,方便点为2的应用(v2)按从小到大,方便点为1的应用(v1)按从大到小排序。贪心,先将v2中的内存和累加,再遍历一遍,每当内存和大于等于m更新一次ans的值,再每次舍弃v2中最小的,去取v1中最大的,因为这样操作能使内存和尽可能的大于或接近m,我们就可以尽可能的少删除应用从而使得失去的方便点尽可能少。
while(t--) {
int n,m; cin >> n >> m;
ll sum=0;
for(int i=1;i<=n;i++) cin >> a[i],sum+=a[i];
for(int i=1;i<=n;i++) cin >> b[i];
if(sum<m)
{
cout << "-1" << endl;
continue;
}
vector<int>v1,v2;
for(int i=1;i<=n;i++)
{
if(b[i]==1) v1.push_back(a[i]);
else v2.push_back(a[i]);
}
sort(v1.begin(),v1.end(),greater<int>());//方便点为1的按照内存从大到小排列
sort(v2.begin(),v2.end());//方便点为2的按照从小到大
ll s=0;
for(auto i : v2) s+=i;//方便点为2的内存和
int tmp=0,ans=INF;
for(int i=0;i<=v2.size();i++)
{
while(tmp<v1.size()&&s<m) s+=v1[tmp],tmp++;//tmp代表选择了多少个方便点为1的应用
if(s>=m) ans=min(ans,(int)(v2.size()-i)*2+tmp);//v2.size()-i代表此时选择了多少个方便点为2的应用
if(i<v2.size()) s-=v2[i];
}
cout << ans << endl;
} E:有n个数,第i个数值为ai,取k个数,要求和最大,问最多有多少中情况。
思路:贪心,从大到小排序,选前k个,看最小值有几个,求组合数。因为数据很小,可以用杨辉三角也可以用lucas。我们在取的时候比较一下当前这个数有多少个与它相等的数,记为cnt,将cnt与k比较,如果cnt<=k,那么就只有一种情况,全选,然后更新k值,k=k-cnt,继续遍历。如果cnt>k,那就说明有多种取法,即组合数C(cnt,k)。下面附上杨辉三角解法。
int main()
{
cin >> t;
comb[0][0] = 1;
for (int i = 1; i <= 1010; i++)
{
comb[i][0] = 1;
for (int j = 1; j <= i; j++)
comb[i][j] = (comb[i - 1][j] + comb[i - 1][j - 1]) % MODNUM;//MODNUM=1000000007
}
while(t--)
{
memset(rec, 0, sizeof(rec));
int n, k;
cin >> n >> k;
for (int j = 1; j <= n; j++)
{
int tmp; cin >> tmp;
rec[tmp]++;
}
for (int j = n; j > 0; j--)
if (rec[j] < k)
k -= rec[j];
else
{
cout << comb[rec[j]][k] << endl;
break;
}
}
return 0;
} 
京公网安备 11010502036488号