T1糖果:
题目描述
幼儿园里有 NN 个小朋友,\text{lxhgww}lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,\text{lxhgww}lxhgww 需要满足小朋友们的 KK 个要求。幼儿园的糖果总是有限的,\text{lxhgww}lxhgww 想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入输出格式
输入格式:
输入的第一行是两个整数 NN,KK。接下来 KK 行,表示这些点需要满足的关系,每行 33 个数字,XX,AA,BB。
- 如果 X=1X=1, 表示第 AA 个小朋友分到的糖果必须和第 BB 个小朋友分到的糖果一样多;
- 如果 X=2X=2, 表示第 AA 个小朋友分到的糖果必须少于第 BB 个小朋友分到的糖果;
- 如果 X=3X=3, 表示第 AA 个小朋友分到的糖果必须不少于第 BB 个小朋友分到的糖果;
- 如果 X=4X=4, 表示第 AA 个小朋友分到的糖果必须多于第 BB 个小朋友分到的糖果;
- 如果 X=5X=5, 表示第 AA 个小朋友分到的糖果必须不多于第 BB 个小朋友分到的糖果;
输出格式:
输出一行,表示 \text{lxhgww}lxhgww 老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出 -1−1。
输入输出样例
输入样例#1: 复制
5 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5 1
输出样例#1: 复制
11
说明
对于 30\%30% 的数据,保证 N\leq100N≤100
对于 100\%100% 的数据,保证 N\leq100000N≤100000
对于所有的数据,保证 K\leq100000, 1\leq X\leq5, 1\leq A, B\leq NK≤100000,1≤X≤5,1≤A,B≤N
#include <bits/stdc++.h>
using namespace std;
#define die {puts("-1"); exit(0);}
typedef long long ll;
struct Edge {
int v, w;
Edge(int v, int w) {
this -> v = v, this -> w = w;
}
};
vector<Edge> G[100005];
int N, K;
bool inq[100005];
int d[100005], cnt[100005];
inline void AddEdge(int u, int v, int w) {
G[u].push_back(Edge(v, w));
}
void SPFA() {
queue<int> q;
q.push(N + 1);
d[N + 1] = 0;
inq[N + 1] = 1;
while (q.size()) {
int u = q.front();
q.pop();
if (cnt[u] >= N) die
cnt[u]++;
inq[u] = 0;
for (vector<Edge>::iterator it = G[u].begin(); it != G[u].end(); it++) {
int v = it -> v, w = it -> w;
if (d[u] + w > d[v]) {
d[v] = d[u] + w;
if (inq[v] == 0) {
inq[v] = 1;
q.push(v);
}
}
}
}
}
int main() {
scanf("%d%d", &N, &K);
for (register int i = 1; i <= K; ++i) {
int X, A, B;
scanf("%d%d%d", &X, &A, &B);
switch (X) {
case 1:
AddEdge(A, B, 0);
AddEdge(B, A, 0);
break;
case 2:
if (A == B) die
AddEdge(A, B, 1);
break;
case 3:
AddEdge(B, A, 0);
break;
case 4:
if (A == B) die
AddEdge(B, A, 1);
break;
case 5:
AddEdge(A, B, 0);
break;
}
}
for (register int i = 1; i <= N; ++i)
AddEdge(N + 1, i, 1);
SPFA();
ll ans = 0;
for (register int i = 1; i <= N; ++i)
ans += d[i];
printf("%lld", ans);
return 0;
}
T2转圈游戏:
#include<bits/stdc++.h>
using namespace std;
int n,m,k,x;
int ksm(int a,int b)
{
int re=1;
int t=a;
while(b)
{
if(b&1) re=re*t%n;
t=t*t%n;
b>>=1;
}
return re;
}
int main()
{
cin>>n>>m>>k>>x;
cout<<(x%n+m%n*ksm(10,k)%n)%n;
return 0;
}
T3Hankson 的趣味题:
题目描述
Hanks 博士是 BT(Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c_1c1 和 c_2c2 的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a_0,a_1,b_0,b_1a0,a1,b0,b1,设某未知正整数xx 满足:
1. xx 和 a_0a0 的最大公约数是 a_1a1;
2. xx 和 b_0b0 的最小公倍数是b_1b1。
Hankson 的“逆问题”就是求出满足条件的正整数xx。但稍加思索之后,他发现这样的xx 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xx 的个数。请你帮助他编程求解这个问题。
输入输出格式
输入格式:
第一行为一个正整数 nn,表示有 nn 组输入数据。接下来的nn 行每行一组输入数据,为四个正整数 a_0,a_1,b_0,b_1a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证 a_0a0 能被 a_1a1 整除,b_1b1 能被b_0b0整除。
输出格式:
共 nn行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的 xx,请输出 00;
若存在这样的xx,请输出满足条件的xx 的个数;
输入输出样例
输入样例#1: 复制
2 41 1 96 288 95 1 37 1776
输出样例#1: 复制
6 2
说明
【说明】
第一组输入数据,xx可以是 9,18,36,72,144,2889,18,36,72,144,288,共有66 个。
第二组输入数据,xx 可以是48,177648,1776,共有 22 个。
【数据范围】
对于 50%的数据,保证有 1≤a_0,a_1,b_0,b_1≤100001≤a0,a1,b0,b1≤10000 且n≤100n≤100。
对于 100%的数据,保证有 1≤a_0,a_1,b_0,b_1≤2,000,000,0001≤a0,a1,b0,b1≤2,000,000,000 且 n≤2000n≤2000。
NOIP 2009 提高组 第二题
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int k=0,f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())
if(c=='-')
f=-1;
for(;isdigit(c);c=getchar())
k=k*10+c-'0';
return k*f;
}
int n,a0,a1,b0,b1,x,ans;
int gcd(int a,int b){
if (b==0) return a;
else return gcd(b,a%b);
}
int main(){
n=read();
while (n>0){
ans=0;
a0=read(),a1=read(),b0=read(),b1=read();
if (a0%a1||b1%b0) {cout<<0<<endl; n--; continue;}
for (int i=1;i*i<=b1;++i)
if (b1%i==0){
x=i;
if (x%a1==0)
if (gcd(a0/a1,x/a1)==1&&gcd(b1/b0,b1/x)==1) ans++;
x=b1/i;
if (x!=i&&x%a1==0)
if (gcd(a0/a1,x/a1)==1&&gcd(b1/b0,b1/x)==1) ans++;
}
cout<<ans<<endl;
n--;
}
}
T4卢卡斯定理:
题目背景
这是一道模板题。
题目描述
给定n,m,p(1\le n,m,p\le 10^51≤n,m,p≤105)
求 C_{n+m}^{m}\ mod\ pCn+mm mod p
保证P为prime
C表示组合数。
一个测试点内包含多组数据。
输入输出格式
输入格式:
第一行一个整数T(T\le 10T≤10),表示数据组数
第二行开始共T行,每行三个数n m p,意义如上
输出格式:
共T行,每行一个整数表示答案。
输入输出样例
输入样例#1: 复制
2 1 2 5 2 1 5
输出样例#1: 复制
3 3
#include<bits/stdc++.h>
using namespace std;
long long n,m,p;
long long pow(long long a,long long k,long long p)
{
long long ret=1;
for(;k;k>>=1,a=(a*a)%p)
if(k&1)ret=(ret*a)%p;
return ret;
}
long long c(long long n,long long m,long long p)
{
if(m>n)return 0;
if(n>=p||m>=p)
return (c(n/p,m/p,p)*c(n%p,m%p,p))%p;
long long ans1=1,ans2=1;
for(int i=m+1;i<=n;i++)ans1=(ans1*i)%p;
for(int i=1;i<=n-m;i++)ans2=(ans2*i)%p;
return (ans1*pow(ans2,p-2,p))%p;
}
int main()
{
int t;
scanf("%d",&t);
for(int k=1;k<=t;k++)
{
scanf("%lld%lld%lld",&n,&m,&p);
printf("%lld\n",c(n+m,m,p));
}
}