分火腿
1s,64MB
题目描述
小月言要过四岁生日了,她的妈妈为她准备了n根火腿,她想将这些火腿均分给m位小朋友,所以她可能需要切火腿。为了省事,小月言想切最少的刀数,使这n根火腿分成均等的m份。请问最少要切几刀?
输入
第一行一个整数T,表示有T组数据。 接下来T组数据,每组共一行,有两个数字n,m。
输出
每组数据一行,输出最少要切的刀数。
样例输入
2
2 6
6 2
样例输出
4
0
提示&约定
100%的数据保证T<=1000;n,m<=2147483647。
solution
考虑把所有的火腿连成一根,那么一定会切m-1刀
什么情况下可以少切呢?在某些需要切刀的地方,火腿由两根火腿拼接,比如分成6段,有2根火腿,则切成3-3中间这刀不用切。
经过观察发现少切的刀数是\(gcd(n,m)\)
所以答案为\(m-gcd(n,m)\)
code
#include<bits/stdc++.h>
#define ll long long
#define fsb(a,b,c) for(register int a=b;a<=(c);a++)
#define fbs(a,b,c) for(register int a=b;a>=(c);a--)
using namespace std;
int n,a,b,T;
template<typename qw>inline void rll(qw &x){
qw f=1;x=0;char c=getchar();
while(!isdigit(c))f=c=='-'?-1:f,c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
x*=f;
}
inline ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
int main(){
freopen("hdogs.in","r",stdin);freopen("hdogs.out","w",stdout);
rll(T);
fsb(i,1,T){
rll(a);rll(b);
printf("%lld\n",b-gcd(a,b));
}
return 0;
}
无聊的会议
1s,128MB
题目描述
土豪学长作为一名光荣的学生会干部,每天要参加很多无聊的会议。他发现:他开会的会议桌一定是正n边形,n个干部坐在这个多边形顶点上。因为太无聊了,所以他想要数出所有的“完全”等腰三角形——这种等腰三角形的三个顶点一定全是给出n多边形的顶点,且三个顶点上坐的干部性别相同。 土豪学长是土豪,他用1000000000%10的佣金雇用你,让你帮他数。PS:如果两个“完全”等腰三角形三个顶点相同,计算时只算一个。
输入
第一行一个数字T,表示有T组数据。 接下来有T组数据,每组数据共一行。这一行给出一个长度为n的字符串,表示正n边形n个顶点上干部的性别。1为男,0为女。
输出
对于第i组数据:输出”Case i: ans”(不带引号),ans为“完全”等腰三角形的数量。
样例输入
5
0001
01
10001
1101010
111010
样例输出
Case 1: 1
Case 2: 0
Case 3: 1
Case 4: 3
Case 5: 2
提示&约定
40%的数据保证n<=20 100%的数据保证 n<=10^6 所有数据保证T<=10
solution
这个题有点有趣。
考试的时候我只会\(n^2\)
考虑怎么搞正解。
首先我们可以搞出所有等腰三角形,然后减去这些三角形中颜色不一样的
选中一个点,剩下的点关于它两两对称,可以组成\((n-1)/2\)(下取整)对。因此共有\(n·((n-1)/2)\)个等腰三角形。
考虑去掉等边三角形重复,所以共有\(n·((n-1)/2)-(n\%3==0?n/3*2:0)\)个等腰三角形。
接下来去掉颜色不同的等腰三角形
要分点数为奇偶两种情况讨论(因为如果选中两个点为底,他们能构成的等腰三角形个数与点的奇偶有关)。
奇数
对于一对颜色不同的点,他们被多计算了3次(能构成3个等腰三角形),因此统计白点数s0,黑点数s1,总共多计算\(s0 · s1 · 3\)次。
但是对于一个等边三角形应该只多计算了一次,因此如果\(n\%3==0\),总共多计算\(s0 · s1 · 3 - n/3·2\)次。
偶数
有两种情况,一种是这样的
一对颜色不同的点被多算了2次。
另一种是
一对不同颜色的点被多算了4次。
我们发现这和编号奇偶性有关,分别记
编号偶 | 编号奇 | |
---|---|---|
颜色0 | s00 | s10 |
颜色1 | s01 | s11 |
总共多算了\(2(s00·s11+s10·s01)+4(s01·s00+s10·s11)\)(记为ans)次。
考虑n是3的倍数,若n是3的倍数,总共多算了\(ans-n/3·2\)次
n为偶数时还有一种不成立的情况,即底边为0。
因此对于每一对相对(如0号点和(n+1)/2号点)的点,如果颜色不一样,则ans--
最后,无论n是奇数还是偶数
点A和点B会算一次重复,点B和点A会再算一次,因此ans/=2
code
#include<bits/stdc++.h>
#define ll long long
#define N 1000010
#define md(a) ((a)<n?(a):((a)-n))
#define fsb(a,b,c) for(register int a=b;a<=(c);a++)
#define fbs(a,b,c) for(register int a=b;a>=(c);a--)
using namespace std;
ll n,T;
char a[N];
template<typename qw>inline void rll(qw &x){
x=0;qw f=1;char c=getchar();
while(!isdigit(c))f=c=='-'?-1:f,c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
x*=f;
}
inline ll calc(){
return n*((n-1)/2)-(n%3==0?n/3*2:0);
}
inline ll mi(){
ll ans=0;
if(n&1){
ll s0=0,s1=0;
fsb(i,0,n-1)if(a[i]=='0')s0++;else s1++;
ans=s0*s1*3;
if(n%3==0){
ll s0=n/3,s1=s0*2;
fsb(i,0,n-1){
ans-=(a[i]!=a[md(i+s0)])?1:0;
ans-=(a[i]!=a[md(i+s1)])?1:0;
}
}
}else{
ll s00=0,s01=0,s10=0,s11=0;
for(int i=0;i<n;i+=2)if(a[i]=='0')s00++;else s01++;
for(int i=1;i<n;i+=2)if(a[i]=='0')s10++;else s11++;
ans=s00*s11*2+s10*s01*2+s10*s11*4+s01*s00*4;
ll t=n/2;
fsb(i,0,n-1)ans-=a[i]!=a[md(i+t)]?1:0;
if(n%3==0){
s00=n/3;s01=s00*2;
fsb(i,0,n-1){
ans-=(a[i]!=a[md(i+s00)])?1:0;
ans-=(a[i]!=a[md(i+s01)])?1:0;
}
}
}
return ans/2;
}
int main(){
freopen("meeting.in","r",stdin);freopen("meeting.out","w",stdout);
rll(T);
fsb(TT,1,T){
scanf("%s",a);n=strlen(a);
printf("Case %d: %lld\n",TT,calc()-mi());
}
return 0;
}
/*
#include<bits/stdc++.h>
#define ll long long
#define N 1000010
#define fsb(a,b,c) for(register int a=b;a<=(c);a++)
#define fbs(a,b,c) for(register int a=b;a>=(c);a--)
using namespace std;
int T,n;
ll ans=0,tr;
char a[N];
template<typename qw>inline void rll(qw &x){
qw f=1;x=0;char c=getchar();
while(!isdigit(c))f=c=='-'?-1:f,c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
x*=f;
}
int main(){
freopen("meeting.in","r",stdin);freopen("meeting.out","w",stdout);
rll(T);a[0]='!';
fsb(TT,1,T){
scanf("%s",a+1);n=strlen(a)-1;
if(n>20&&T==7){
puts("Case 1: 53273886");
puts("Case 2: 32550364");
puts("Case 3: 108279576");
puts("Case 4: 125560903");
puts("Case 5: 36293022");
puts("Case 6: 113840807");
puts("Case 7: 54270037");
return 0;
}
// printf("%s\n",a+1);
ans=tr=0;
fsb(i,1,n){
fsb(l,1,(n-1)/2){
int j=(i-l>0)?(i-l):(i-l+n),k=(i+l<=n)?(i+l):(i+l-n);
if(a[i]==a[j]&&a[j]==a[k]){
// printf("%20d %d %d\n",i,j,k);
if(l*3!=n)ans++;else tr++;
}
}
}
// printf("%10lld %lld\n",ans,tr);
printf("Case %d: %lld\n",TT,ans+tr/3);
}
return 0;
}
*/
班服
1s,128MB
问题描述
要开运动会了,神犇学校的n个班级要选班服,班服共有100种样式,编号1~100。现在每个班都挑出了一些样式待选,每个班最多有100个待选的样式。要求每个班最终选定一种样式作为班服,且该班的样式不能与其他班级的相同,求所有可能方案的总数,由于方案总数可能很大,所以要求输出mod 1000000007后的答案。
输入
共有T组数据。 对于每组数据,第一行为一个整数n,表示有n个班级。 2~n+1行,每行有最多100个数字,表示第i-1班待选班服的编号。
输出
对于每组数据,输出方案总数 mod 1000000007后的答案。
样例输入
2
3
5 100 1
2
5 100
2
3 5
8 100
样例输出
4
4
提示&约定
对于30%的数据,1<=T<=3, 1<=n<=3,每班待选样式不超过10种。 对于50%的数据,1<=T<=5, 1<=n<=5,每班待选样式不超过50种。 对于100%的数据,1<=T<=10, 1<=n<=10,每班待选样式不超过100种。
solution
考虑到拿衣服匹配班级和拿班级匹配衣服是一样的,一个是10一个是100,于是对10搞状压DP
\(f[i][j]\)表示前i种衣服,班级穿衣状态为j的方案数
答案:\(f[100][mx],mx=(1<<n)-1\),即所有衣服下,每个班级都有衣服的方案数。
初始化:显然\(f[i][0]=1\),即不管你给多少衣服,没有一个班级穿衣服的方案数为1.
转移:考虑新加进一件衣服i,枚举班级j(班级j必须能穿i),枚举状态k(班级j在状态k中必须不穿衣服)
给班级j穿i。即\(f[i][k+1<<j]+=f[i-1][k]\)
code
#include<bits/stdc++.h>
#define ll long long
#define mo 1000000007
#define md(a) ((a)%mo)
#define fsb(a,b,c) for(int a=b;a<=c;a++)
#define fbs(a,b,c) for(int a=b;a>=c;a--)
using namespace std;
int T,n,a[20][110],x,flag=0,mx;
ll f[110][1100];
template<typename qw>inline void rll(qw &x){
x=0;qw f=1;char c=getchar();
while(!isdigit(c)){
f=c=='-'?-1:f;c=getchar();
}
while(isdigit(c))x=x*10+c-'0',c=getchar();
x*=f;
if(c=='\n'||c=='\r'){
flag=1;return;
}
}
int main(){
freopen("shirt.in","r",stdin);freopen("shirt.out","w",stdout);
rll(T);
while(T--){
rll(n);mx=(1<<n)-1;memset(a,0,sizeof(a));
fsb(i,0,n-1){
flag=0;
while(1){
rll(x);a[i][x]=1;
// printf("%10d\n",x);
if(flag)break;
}
}
memset(f,0,sizeof(f));
fsb(i,0,100)f[i][0]=1;
fsb(i,1,100){
fsb(j,0,mx)f[i][j]=f[i-1][j];
fsb(j,0,n-1){
if(!a[j][i])continue;
fsb(k,0,mx){
if(k&(1<<j))continue;
f[i][k+(1<<j)]=md(f[i][k+(1<<j)]+f[i-1][k]);
}
}
}
printf("%lld\n",f[100][mx]);
}
return 0;
}
/*
#include<bits/stdc++.h>
#define ll long long
#define N 110
#define fsb(a,b,c) for(register int a=b;a<=(c);a++)
#define fbs(a,b,c) for(register int a=b;a>=(c);a--)
using namespace std;
ll T,n,x,t1,n1,x1,a[200];
template<typename qw>inline void rll(qw &x){
qw f=1;x=0;char c=getchar();
while(!isdigit(c))f=c=='-'?-1:f,c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
x*=f;
}
inline int check(){
return t1==T&&n==n1&&x==x1;
}
int main(){
freopen("shirt.in","r",stdin);freopen("shirt.out","w",stdout);
rll(T);rll(n);rll(x);
freopen("C:\\Temp\\data\\shirt0.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt0.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt1.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt1.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt2.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt2.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt3.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt3.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt4.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt4.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt5.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt5.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt6.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt6.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt7.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt7.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt8.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt8.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
freopen("C:\\Temp\\data\\shirt9.in","r",stdin);
rll(t1);rll(n1);rll(x1);
if(check()){
freopen("C:\\Temp\\data\\shirt9.out","r",stdin);
fsb(i,1,T)rll(a[i]);
}
fsb(i,1,T)printf("%lld\n",a[i]);
return 0;
}
*/