题目描述
一个长度为n+m+k,包含n个数字2,m个数字5和k个数字6的序列,最多可能有多少个子序列是2526? 如果一个序列是数组的子序列,当且仅当这个序列可以由数组删去任意个元素,再将数组中的剩余元素按顺序排列而成。
输入格式
第一行一个整数t,表示测试用例的组数。 接下来t行每行三个整数nm,k表示一组测试用例。
输出格式
对于每组测试用例输出一行一个整数表示答案。
样例输入
3 6 7 8 1 2 2 6 0 3
样例输出
504 0 0
数据范围与提示
1<=t<=200000 0<=n,m,k<=10000
思路
把n分成2份,即n/2
然后求排列
如下:
n*m*n*k
注意
n为奇数时其中一个n除完要加1
#include
using namespace std;
long long int n,m,k,tmp,ans,t,bj;
int main()
{
cin>>t;
for(int i=1;i<=t;i++)//多组测试数据
{
scanf("%lld%lld%lld",&n,&m,&k);
tmp=n/2;
n=n-tmp;//加1操作 因为tmp是n/2,那n-tmp就是已经n的一半,加1操作也有了
ans=n*m*tmp*k;
cout<
这题想思路的时候慢了点
但想到了就挺好做的
注意
一定比赛要检查程序
旁边的一位没检查程序,漏了换行
题目描述
给你两个非负的整数L,R,在区间[L,R]中找两个不同的数,使得它们的乘积模2019最小,输出这个结果。
输入格式
第一行两个整数L,R
输出格式
一行,表示mod 2019的最小值。
输入样例1
2020 2040
输出样例1
2
输入样例2
4 5
输出样例2
20
数据范围与提示
0<=L<=R<=$10^9$
要往2019的倍数去想
只要R-L>=2019那么就一定有2019的倍数,那么2019的倍数乘以任何数都可以被2019整除
那剩下的就暴力就好了
所以这题就变简单了
算出R-L,大于等于2019的话直接输出0,小于2019的话做暴力做法
虽然暴力的时间复杂都还是O($n^2$),但暴力只用处理2019以下的数据
怎么暴力就不说了 懂得都懂
#include
using namespace std;
long long int l,r,minn=2020;
int main()
{
cin>>l>>r;
if(r-l>=2019)//大于的情况
{
cout<<0;
return 0;
}
for(long long i=l;i<=r;i++)//由于数据较大,相乘要开long long 类型
{
for(long long j=l;j<=r;j++)//暴力
{
if(i==j) continue;
minn=min(i*j%2019,minn);
}
}
cout<
这题思路就是倍数,但在coding的时候没有想到i,j要开long long ,所以痛失44分
题目描述
有n座山排成一个圆环,编号为1~n。两座山之间有一个水坝。第i座山和第i+1座山之间的水坝称为第i个水坝。因为山是环形的,第n+1座山也是第1座山。第n+1个水坝也是第1个水坝。如果第i座山降雨量为2Li,则它的降雨量会平均地分到相邻的两座水坝去。假设水坝的水全是由山上的降雨提供。现在给出每一座水坝收到的水量,问每座山的降雨量。n是奇数。
输入格式
第一行一个整数n 接下来第二行有n个整数,表示每座水坝的水量。
输出格式
输出一行,共有n个数,表示每座山的降雨量。
输入样例1
3 2 2 4
输出样例1
4 0 4
这题是一个二分的思路,mid枚举第一座山的降雨量的一半,通过暴力求出mid是否可行,可行就输出,mid小了则最后的水库1和水库n必有一水库水多了,mid大了着相反,这样求一个单调mid。
#include
using namespace std;
long long int waterku[200000],taxtwaterku[200000],n;
int check(long long int x)//检查mid值是否可行
{
for(int i=1;i<=n;i++) taxtwaterku[i]=waterku[i];
taxtwaterku[1]-=x;
taxtwaterku[n]-=x;
for(int i=2;i<=n;i++)
{
int u=min(taxtwaterku[i],taxtwaterku[i-1]);
taxtwaterku[i]-=u;
taxtwaterku[i-1]-=u;
}
int flag=1;
for(int i=1;i<=n;i++)
{
if(taxtwaterku[i]>0) flag=0;
}
if(flag==1) return 1;
else if(taxtwaterku[1]>0||taxtwaterku[n]>0) return 2;
else return 3;
}
int out(long long int x)//输出把mid在枚举一遍
{
for(int i=1;i<=n;i++) taxtwaterku[i]=waterku[i];
taxtwaterku[1]-=x;
taxtwaterku[n]-=x;
cout<>n;
for(int i=1;i<=n;i++)
{
cin>>waterku[i];
}
int l=0,r=max(waterku[1],waterku[n]);
while(l<=r)//二分,这里是l<=r
{
long long int mid=(l+r)/2;
int flag=check(mid);
if(flag==1)
{
out(mid);
}
else if(flag==2)
l=mid+1;
else
r=mid;
}
}
这题挺简单的,可惜考试是没有想出来。想到了二分,但没有想到mid枚举什么。
题目描述
有一棵树,包含n个点,n-1条边,第i条边的两个端点为ui,vi,现在你要对所有的点染色,你一共有K种颜色。染色要求符合以下条件:
- 对两个距离小于等于2的不同顶点,它们必须染成不一样的颜色。
问有多少种染色的方案。输出模$10^9+7$的结果。
输入格式
第一行两个数,表示N和K。 接下来有N-1行,每一行两个整数,表示一条边的两个端点。
输出格式
一个答案。
输入样例1
4 3 1 2 2 3 3 4
输出样例1
6
数据范围与提示
1<=n,k<=$10^5$ 1<=$u_i$,$v_i$<=n
DFS推导,一个节点的贡献量即为k-爸爸-兄弟,在把贡献相乘即可。
#include
using namespace std;
long long nex[1000000],a[1000000],p[1000000],num[1000000],bj[1000000],ans=1,cn,n,k;
int dfs(int x,int fa,int br)
{
ans*=k-fa-br;//方案数
ans%=1000000007;
bj[x]=1;
int t=0;
for(int i=num[x];i;i=nex[i])
{
if(bj[a[i]]==1) continue;
if(fa+1<=2)
{
dfs(a[i],fa+1,t);
}
else
{
dfs(a[i],fa,t);
}
t++;
}
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
cn++;
a[cn]=u;
nex[cn]=num[v];
num[v]=cn;
cn++;
a[cn]=v;
nex[cn]=num[u];
num[u]=cn;//链式前向星
}
dfs(1,0,0);
cout<
这题要仔细思考每个点的贡献,再用排列法求解
这次题目并不难,只是没有认真思考。
也没有进行结束检查,在考试范低级错误丢分是很严重的问题。
以后考试后30分钟要记得检查。
还要提升自己的思维和代码实践能力。