题目链接
A - Couple doubi
题意:桌上共有 k 个球,第i个球的值为 (1^i+2^i+...+(p-1)^i )mod p#include
int main()
{
int p,n;
while(scanf("%d%d",&n,&p)!=EOF){
if((n/(p-1))%2)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
#include
#include
#define N 100000
using namespace std;
struct stu{
int time,level;
}task[N+10],machine[N+10];
int cmp(stu a,stu b){
if(a.time==b.time)
return a.level>b.level;
return a.time>b.time;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=1;i<=n;i++)
scanf("%d%d",&machine[i].time,&machine[i].level);
for(int i=1;i<=m;i++)
scanf("%d%d",&task[i].time,&task[i].level);
sort(machine+1,machine+1+n,cmp);
sort(task+1,task+1+m,cmp);
int j=1,cnt[105]={0},maxm=0;
long long ans=0;
for(int i=1;i<=m;i++){
while(j<=n&&task[i].time<=machine[j].time){
cnt[machine[j].level]++;
j++;
}
for(int k=task[i].level;k<=100;k++){
if(cnt[k]){
maxm++;
ans+=task[i].time*500+task[i].level*2;
cnt[k]--;
break;
}
}
}
printf("%d %I64d\n",maxm,ans);
}
return 0;
}
#include
#include
#include
char Con[5][10]={"Dry","Dryish","Damp","Soggy"};
char We[5][10]={"Sunny","Cloudy","Rainy"};
double lePro[3][4]={0.6,0.2,0.15,0.05,
0.25,0.3,0.2,0.25,
0.05,0.10,0.35,0.50}; //叶子
double wePro[3][3]={0.5,0.375,0.125,
0.25,0.125,0.625,
0.25,0.375,0.375}; //天气
double init[3]={0.63,0.17,0.2};
double dp[55][3],pre[55][3];
int n,lePos[55];
void solve()
{
for(int i=0;i<3;i++)
dp[1][i]=log(init[i])+log(lePro[i][lePos[1]]);
for(int i=2;i<=n;i++){
for(int j=0;j<3;j++){ //今天天气
double maxp=-1e8;
int pos=0;
for(int k=0;k<3;k++){ //昨天天气
double temp=dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]]);
if(temp>maxp){
maxp=temp;
pos=k;
}
}
dp[i][j]=maxp;
pre[i][j]=pos;
}
}
}
int main()
{
int T;
scanf("%d",&T);
for(int k=1;k<=T;k++){
printf("Case #%d:\n",k);
scanf("%d",&n);
char con[10];
for(int i=1;i<=n;i++){
scanf("%s",con);
for(int j=0;j<4;j++)
if(strcmp(con,Con[j])==0){
lePos[i]=j;
break;
}
}
solve();
double maxp=-1e8;
int ans[55];
for(int i=0;i<3;i++)
if(dp[n][i]>maxp){
maxp=dp[n][i];
ans[n]=i;
}
for(int i=n-1;i>=1;i--)
ans[i]=pre[i+1][ans[i+1]];
for(int i=1;i<=n;i++)
printf("%s\n",We[ans[i]]);
}
return 0;
}
可以观察到的状态序列和隐藏的状态序列是概率相关的
I - Turn the pokers
题意:有m张牌,初始状态都是正面朝下,现在要进行n次操作,
第i次操作要翻ai张牌,求n次操作后,牌的状态可能有多少种?
分析:牌只有两种状态,设面朝下为0,面朝上为1,则初始状态都为0
很显然每一张牌的状态只跟这张牌被翻的次数的奇偶性有关。
翻牌i次后1的个数的奇偶性一定与前i次翻牌的总张数 a1+a2+...+ai的奇偶性相同
(初始状态1的个数为0,是偶数,1.若翻偶数张牌,1的个数还是偶数
2.若翻奇数张,得到的还是奇数,
在第2种情况下若再翻奇数次,可能会翻奇数个0,偶数个1,或者偶数个0,奇数个1,
结果还是奇数,而两次翻牌张数和为偶加奇,也是奇数。。。可自行证明)
若终态有最少有min个1,最多有max个1,那么1的个数可能为 min,min+2,min+4,...,max
即牌的状态可能有 C(m,min)+C(m,min+2)+C(m,min+4)+...+C(m,max) 种
这样就转化为求min,max及组合数了
C(m,i)=m!/(i!*(m-i)!),因为最终要取余,而阶乘数太大存不了,还涉及到除法,
直接取余再除肯定不行(同余定理不适用于除法)
可以利用费马小定理解决:
由定理得:a^(p-1)≡1%p
则 a^(p-2)≡1/a%p
因为p很大,需要用快速幂取余来做
#include
#define N 100000
#define mod 1000000009
#define LL long long
LL fact[N+10];
void init()
{
fact[0]=1;
for(int i=1;i<=N;i++)
fact[i]=fact[i-1]*i%mod;
}
LL powMod(LL a,LL b)
{
LL ans=1;
a%=mod;
while(b){
if(b%2)
ans=ans*a%mod;
b/=2;
a=a*a%mod;
}
return ans;
}
int main()
{
int n,m;
init();
while(scanf("%d%d",&n,&m)!=EOF){ //m张扑克,n次操作
int min1,max1,tempMin=0,tempMax=0; //1的最小最大个数
while(n--){
int x;
scanf("%d",&x);
//计算最少的1,要尽可能让1->0
if(x<=tempMin)
min1=tempMin-x;
else if(x<=tempMax){
if((x%2)==(tempMin%2))
min1=0;
else
min1=1;
}
else
min1=x-tempMax;
//计算最多的1,要尽可能让0->1
if(x<=m-tempMax)
max1=tempMax+x;
else if(x<=m-tempMin){
if((x%2)==((m-tempMin)%2))
max1=m;
else
max1=m-1;
}
else
max1=m-(x-(m-tempMin));
tempMin=min1;
tempMax=max1;
}
LL ans=0;
for(int i=min1;i<=max1;i+=2) //费马小定理
ans=(ans+(fact[m]*powMod(fact[i]*fact[m-i],mod-2))%mod)%mod;
printf("%I64d\n",ans);
}
return 0;
}
#include
#include
#include